From f72ad02f5ec370f45995ecd2b3e8b322e9a7e4dc Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 26 Jul 2010 15:33:30 -0700 Subject: New branch with firmware dir from USRP2P branch. --- firmware/microblaze/.gitignore | 2 + firmware/microblaze/Makefile.am | 7 +- firmware/microblaze/Makefile.common | 37 +- firmware/microblaze/apps/blinkenlights.c | 26 + firmware/microblaze/apps/cruft/Makefile.am | 82 ++ firmware/microblaze/apps/cruft/app_passthru_v2.c | 251 ++++++ firmware/microblaze/apps/cruft/app_passthru_v2.h | 54 ++ firmware/microblaze/apps/cruft/blink_leds.c | 40 + firmware/microblaze/apps/cruft/blink_leds2.c | 53 ++ firmware/microblaze/apps/cruft/buf_ram_test.c | 89 +++ firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c | 106 +++ firmware/microblaze/apps/cruft/burnrev30.c | 162 ++++ firmware/microblaze/apps/cruft/burnrev31.c | 162 ++++ firmware/microblaze/apps/cruft/can_i_sub.c | 25 + .../microblaze/apps/cruft/double_buffer_fragment.c | 138 ++++ firmware/microblaze/apps/cruft/echo.c | 34 + firmware/microblaze/apps/cruft/eth_serdes.c | 233 ++++++ firmware/microblaze/apps/cruft/factory_test.c | 438 +++++++++++ firmware/microblaze/apps/cruft/gen_eth_packets.c | 187 +++++ firmware/microblaze/apps/cruft/gen_pause_frames.c | 207 +++++ firmware/microblaze/apps/cruft/hello.c | 30 + firmware/microblaze/apps/cruft/ibs_rx_test.c | 82 ++ firmware/microblaze/apps/cruft/ibs_tx_test.c | 160 ++++ .../microblaze/apps/cruft/mimo_app_common_v2.c | 582 ++++++++++++++ .../microblaze/apps/cruft/mimo_app_common_v2.h | 63 ++ firmware/microblaze/apps/cruft/mimo_tx.c | 363 +++++++++ firmware/microblaze/apps/cruft/mimo_tx_slave.c | 376 +++++++++ firmware/microblaze/apps/cruft/rcv_eth_packets.c | 233 ++++++ firmware/microblaze/apps/cruft/read_dbids.c | 59 ++ firmware/microblaze/apps/cruft/sd_bounce.c | 153 ++++ firmware/microblaze/apps/cruft/sd_gentest.c | 269 +++++++ firmware/microblaze/apps/cruft/serdes_to_dsp.c | 179 +++++ firmware/microblaze/apps/cruft/serdes_txrx.c | 368 +++++++++ firmware/microblaze/apps/cruft/set_hw_rev.c | 45 ++ firmware/microblaze/apps/cruft/test1.c | 282 +++++++ firmware/microblaze/apps/cruft/test_db_spi.c | 35 + firmware/microblaze/apps/cruft/test_i2c.c | 108 +++ firmware/microblaze/apps/cruft/test_lsadc.c | 57 ++ firmware/microblaze/apps/cruft/test_lsdac.c | 51 ++ firmware/microblaze/apps/cruft/test_phy_comm.c | 113 +++ firmware/microblaze/apps/cruft/test_ram.c | 105 +++ firmware/microblaze/apps/cruft/test_sd.c | 81 ++ firmware/microblaze/apps/cruft/timer_test.c | 57 ++ firmware/microblaze/apps/cruft/tx_standalone.c | 339 +++++++++ firmware/microblaze/apps/flash_test.c | 67 ++ firmware/microblaze/apps/hardware_testbed.c | 47 ++ firmware/microblaze/apps/txrx_uhd.c | 3 +- firmware/microblaze/apps/uart_flash_loader.c | 169 +++++ firmware/microblaze/bin/bin_to_mif.py | 29 + firmware/microblaze/bin/bin_to_ram_macro_init.py | 48 ++ firmware/microblaze/bin/elf_to_sbf | 142 ++++ firmware/microblaze/bin/sbf.py | 134 ++++ firmware/microblaze/bin/serial_loader | 363 +++++++++ firmware/microblaze/bin/uart_ihex_flash_loader.py | 138 ++++ firmware/microblaze/bin/uart_ihex_ram_loader.py | 70 ++ firmware/microblaze/bootstrap | 2 + firmware/microblaze/configure.ac | 8 +- firmware/microblaze/lib/Makefile.inc | 48 ++ firmware/microblaze/lib/bootconfig.c | 101 +++ firmware/microblaze/lib/clock_bits.h | 55 ++ firmware/microblaze/lib/clocks.h | 2 +- firmware/microblaze/lib/compiler.h | 25 + firmware/microblaze/lib/ethernet.c | 11 +- firmware/microblaze/lib/gdbstub2.c | 506 +++++++++++++ firmware/microblaze/lib/gdbstub2.h | 25 + firmware/microblaze/lib/hal_io.c | 10 + firmware/microblaze/lib/hal_io.h | 1 + firmware/microblaze/lib/hal_uart.c | 13 +- firmware/microblaze/lib/hal_uart.h | 10 + firmware/microblaze/lib/ihex.c | 57 ++ firmware/microblaze/lib/ihex.h | 18 + firmware/microblaze/lib/loader_parser.c | 324 ++++++++ firmware/microblaze/lib/loader_parser.h | 38 + firmware/microblaze/lib/net/.gitignore | 2 + firmware/microblaze/lib/net/eth_mac_addr.h | 29 + firmware/microblaze/lib/net/padded_eth_hdr.h | 37 + firmware/microblaze/lib/net/socket_address.h | 41 + firmware/microblaze/lib/nonstdio.c | 43 ++ firmware/microblaze/lib/nonstdio.h | 10 +- firmware/microblaze/lib/spi.h | 18 + firmware/microblaze/lib/u2_init.c | 8 +- firmware/microblaze/lib/udp_burner_packet.c | 38 + firmware/microblaze/lib/udp_burner_packet.h | 28 + firmware/microblaze/lib/xilinx_s3_icap.c | 101 +++ firmware/microblaze/usrp2/.gitignore | 9 + firmware/microblaze/usrp2/Makefile.am | 43 ++ firmware/microblaze/usrp2/clocks.c | 239 ++++++ firmware/microblaze/usrp2/memory_map.h | 793 +++++++++++++++++++ firmware/microblaze/usrp2/sd.c | 197 +++++ firmware/microblaze/usrp2/sd.h | 122 +++ firmware/microblaze/usrp2p/.gitignore | 9 + firmware/microblaze/usrp2p/Makefile.am | 66 ++ firmware/microblaze/usrp2p/bootconfig.h | 61 ++ firmware/microblaze/usrp2p/bootloader/.gitignore | 11 + firmware/microblaze/usrp2p/bootloader/Makefile.am | 39 + .../microblaze/usrp2p/bootloader/fpga_bootloader.c | 202 +++++ .../microblaze/usrp2p/bootloader/fw_bootloader.c | 50 ++ firmware/microblaze/usrp2p/bootloader/icap_test.c | 31 + .../microblaze/usrp2p/bootloader/init_bootloader.c | 108 +++ .../usrp2p/bootloader/serial_loader_burner.c | 49 ++ .../microblaze/usrp2p/bootloader/spi_bootloader.c | 134 ++++ firmware/microblaze/usrp2p/bootloader/u2p2-rom.ld | 190 +++++ firmware/microblaze/usrp2p/bootloader_utils.c | 33 + firmware/microblaze/usrp2p/bootloader_utils.h | 21 + firmware/microblaze/usrp2p/clocks.c | 259 +++++++ firmware/microblaze/usrp2p/memory_map.h | 838 +++++++++++++++++++++ firmware/microblaze/usrp2p/spi_flash.c | 194 +++++ firmware/microblaze/usrp2p/spi_flash.h | 112 +++ firmware/microblaze/usrp2p/spi_flash_private.h | 70 ++ firmware/microblaze/usrp2p/spi_flash_read.c | 100 +++ firmware/microblaze/usrp2p/spif.c | 68 ++ firmware/microblaze/usrp2p/xilinx_s3_icap.h | 37 + 112 files changed, 13382 insertions(+), 45 deletions(-) create mode 100644 firmware/microblaze/apps/blinkenlights.c create mode 100644 firmware/microblaze/apps/cruft/Makefile.am create mode 100644 firmware/microblaze/apps/cruft/app_passthru_v2.c create mode 100644 firmware/microblaze/apps/cruft/app_passthru_v2.h create mode 100644 firmware/microblaze/apps/cruft/blink_leds.c create mode 100644 firmware/microblaze/apps/cruft/blink_leds2.c create mode 100644 firmware/microblaze/apps/cruft/buf_ram_test.c create mode 100644 firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c create mode 100644 firmware/microblaze/apps/cruft/burnrev30.c create mode 100644 firmware/microblaze/apps/cruft/burnrev31.c create mode 100644 firmware/microblaze/apps/cruft/can_i_sub.c create mode 100644 firmware/microblaze/apps/cruft/double_buffer_fragment.c create mode 100644 firmware/microblaze/apps/cruft/echo.c create mode 100644 firmware/microblaze/apps/cruft/eth_serdes.c create mode 100644 firmware/microblaze/apps/cruft/factory_test.c create mode 100644 firmware/microblaze/apps/cruft/gen_eth_packets.c create mode 100644 firmware/microblaze/apps/cruft/gen_pause_frames.c create mode 100644 firmware/microblaze/apps/cruft/hello.c create mode 100644 firmware/microblaze/apps/cruft/ibs_rx_test.c create mode 100644 firmware/microblaze/apps/cruft/ibs_tx_test.c create mode 100644 firmware/microblaze/apps/cruft/mimo_app_common_v2.c create mode 100644 firmware/microblaze/apps/cruft/mimo_app_common_v2.h create mode 100644 firmware/microblaze/apps/cruft/mimo_tx.c create mode 100644 firmware/microblaze/apps/cruft/mimo_tx_slave.c create mode 100644 firmware/microblaze/apps/cruft/rcv_eth_packets.c create mode 100644 firmware/microblaze/apps/cruft/read_dbids.c create mode 100644 firmware/microblaze/apps/cruft/sd_bounce.c create mode 100644 firmware/microblaze/apps/cruft/sd_gentest.c create mode 100644 firmware/microblaze/apps/cruft/serdes_to_dsp.c create mode 100644 firmware/microblaze/apps/cruft/serdes_txrx.c create mode 100644 firmware/microblaze/apps/cruft/set_hw_rev.c create mode 100644 firmware/microblaze/apps/cruft/test1.c create mode 100644 firmware/microblaze/apps/cruft/test_db_spi.c create mode 100644 firmware/microblaze/apps/cruft/test_i2c.c create mode 100644 firmware/microblaze/apps/cruft/test_lsadc.c create mode 100644 firmware/microblaze/apps/cruft/test_lsdac.c create mode 100644 firmware/microblaze/apps/cruft/test_phy_comm.c create mode 100644 firmware/microblaze/apps/cruft/test_ram.c create mode 100644 firmware/microblaze/apps/cruft/test_sd.c create mode 100644 firmware/microblaze/apps/cruft/timer_test.c create mode 100644 firmware/microblaze/apps/cruft/tx_standalone.c create mode 100644 firmware/microblaze/apps/flash_test.c create mode 100644 firmware/microblaze/apps/hardware_testbed.c create mode 100644 firmware/microblaze/apps/uart_flash_loader.c create mode 100755 firmware/microblaze/bin/bin_to_mif.py create mode 100755 firmware/microblaze/bin/bin_to_ram_macro_init.py create mode 100755 firmware/microblaze/bin/elf_to_sbf create mode 100644 firmware/microblaze/bin/sbf.py create mode 100755 firmware/microblaze/bin/serial_loader create mode 100755 firmware/microblaze/bin/uart_ihex_flash_loader.py create mode 100755 firmware/microblaze/bin/uart_ihex_ram_loader.py create mode 100644 firmware/microblaze/lib/Makefile.inc create mode 100644 firmware/microblaze/lib/bootconfig.c create mode 100644 firmware/microblaze/lib/clock_bits.h create mode 100644 firmware/microblaze/lib/compiler.h create mode 100644 firmware/microblaze/lib/gdbstub2.c create mode 100644 firmware/microblaze/lib/gdbstub2.h create mode 100644 firmware/microblaze/lib/ihex.c create mode 100644 firmware/microblaze/lib/ihex.h create mode 100644 firmware/microblaze/lib/loader_parser.c create mode 100644 firmware/microblaze/lib/loader_parser.h create mode 100644 firmware/microblaze/lib/net/.gitignore create mode 100644 firmware/microblaze/lib/net/eth_mac_addr.h create mode 100644 firmware/microblaze/lib/net/padded_eth_hdr.h create mode 100644 firmware/microblaze/lib/net/socket_address.h create mode 100644 firmware/microblaze/lib/udp_burner_packet.c create mode 100644 firmware/microblaze/lib/udp_burner_packet.h create mode 100644 firmware/microblaze/lib/xilinx_s3_icap.c create mode 100644 firmware/microblaze/usrp2/.gitignore create mode 100644 firmware/microblaze/usrp2/Makefile.am create mode 100644 firmware/microblaze/usrp2/clocks.c create mode 100644 firmware/microblaze/usrp2/memory_map.h create mode 100644 firmware/microblaze/usrp2/sd.c create mode 100644 firmware/microblaze/usrp2/sd.h create mode 100644 firmware/microblaze/usrp2p/.gitignore create mode 100644 firmware/microblaze/usrp2p/Makefile.am create mode 100644 firmware/microblaze/usrp2p/bootconfig.h create mode 100644 firmware/microblaze/usrp2p/bootloader/.gitignore create mode 100644 firmware/microblaze/usrp2p/bootloader/Makefile.am create mode 100644 firmware/microblaze/usrp2p/bootloader/fpga_bootloader.c create mode 100644 firmware/microblaze/usrp2p/bootloader/fw_bootloader.c create mode 100644 firmware/microblaze/usrp2p/bootloader/icap_test.c create mode 100644 firmware/microblaze/usrp2p/bootloader/init_bootloader.c create mode 100644 firmware/microblaze/usrp2p/bootloader/serial_loader_burner.c create mode 100644 firmware/microblaze/usrp2p/bootloader/spi_bootloader.c create mode 100644 firmware/microblaze/usrp2p/bootloader/u2p2-rom.ld create mode 100644 firmware/microblaze/usrp2p/bootloader_utils.c create mode 100644 firmware/microblaze/usrp2p/bootloader_utils.h create mode 100644 firmware/microblaze/usrp2p/clocks.c create mode 100644 firmware/microblaze/usrp2p/memory_map.h create mode 100644 firmware/microblaze/usrp2p/spi_flash.c create mode 100644 firmware/microblaze/usrp2p/spi_flash.h create mode 100644 firmware/microblaze/usrp2p/spi_flash_private.h create mode 100644 firmware/microblaze/usrp2p/spi_flash_read.c create mode 100644 firmware/microblaze/usrp2p/spif.c create mode 100644 firmware/microblaze/usrp2p/xilinx_s3_icap.h (limited to 'firmware') diff --git a/firmware/microblaze/.gitignore b/firmware/microblaze/.gitignore index 068f01838..e867fe87c 100644 --- a/firmware/microblaze/.gitignore +++ b/firmware/microblaze/.gitignore @@ -5,6 +5,8 @@ /*.log /*.rom /.deps +/*.guess +/*.sub /Makefile /Makefile.in /aclocal.m4 diff --git a/firmware/microblaze/Makefile.am b/firmware/microblaze/Makefile.am index 676c4fe42..ffc59192d 100644 --- a/firmware/microblaze/Makefile.am +++ b/firmware/microblaze/Makefile.am @@ -22,6 +22,7 @@ include $(top_srcdir)/Makefile.common EXTRA_DIST = \ u2_flash_tool -SUBDIRS = include lib apps - - +SUBDIRS = \ + usrp2 \ + usrp2p \ + usrp2p/bootloader diff --git a/firmware/microblaze/Makefile.common b/firmware/microblaze/Makefile.common index 3d0f540d8..ceb6a553a 100644 --- a/firmware/microblaze/Makefile.common +++ b/firmware/microblaze/Makefile.common @@ -17,6 +17,8 @@ # along with this program. If not, see . # +include $(top_srcdir)/lib/Makefile.inc + ######################################################################## # lwIP header include dirs ######################################################################## @@ -28,13 +30,6 @@ LWIP_INCLUDES = \ -I$(LWIPDIR)/src/include \ -I$(LWIPDIR)/src/include/ipv4 -######################################################################## -# local include dirs -######################################################################## -LOCAL_INCLUDES = \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/lib - ######################################################################## # misc flags for the mb-gcc compiler ######################################################################## @@ -42,8 +37,6 @@ MBGCC_CFLAGS = \ --std=gnu99 -Wall -Werror-implicit-function-declaration \ -mxl-soft-div -msoft-float -mxl-soft-mul -mxl-barrel-shift -MBGCC_LFLAGS = -Wl,-defsym -Wl,_STACK_SIZE=3072 - ######################################################################## # define for the hal io (FIXME move?) ######################################################################## @@ -51,31 +44,39 @@ MBGCC_LFLAGS = -Wl,-defsym -Wl,_STACK_SIZE=3072 HAL_IO = -DHAL_IO_USES_UART ######################################################################## -# set the cflags and ldflags +# common cflags and ldflags ######################################################################## -AM_CFLAGS = $(MBGCC_CFLAGS) $(LOCAL_INCLUDES) $(LWIP_INCLUDES) $(HAL_IO) +COMMON_CFLAGS = \ + -I$(top_srcdir)/../../host/lib/usrp \ + -I$(top_srcdir)/lib \ + $(MBGCC_CFLAGS) \ + $(LWIP_INCLUDES) \ + $(HAL_IO) -AM_LDFLAGS = $(MBGCC_LFLAGS) +COMMON_LFLAGS = \ + -Wl,-Map -Wl,$(@:.elf=.map) ######################################################################## # Common stuff for building top level microblaze images ######################################################################## -AM_LDFLAGS += -Wl,-Map -Wl,$(@:.elf=.map) - -%.bin : %.elf +.elf.bin: $(MB_OBJCOPY) -O binary $< $@ -%.dump : %.elf +.elf.dump: $(MB_OBJDUMP) -DSC $< > $@ -%.rom : %.bin +.bin.rom: $(HEXDUMP) -v -e'1/1 "%.2X\n"' $< > $@ +.elf.ihx: + $(MB_OBJCOPY) -O ihex $(COMMON_IHX_ARGS) $< $@ + _generated_from_elf = \ $(noinst_PROGRAMS:.elf=.map) \ $(noinst_PROGRAMS:.elf=.bin) \ $(noinst_PROGRAMS:.elf=.dump) \ - $(noinst_PROGRAMS:.elf=.rom) + $(noinst_PROGRAMS:.elf=.rom) \ + $(noinst_PROGRAMS:.elf=.ihx) noinst_DATA = $(_generated_from_elf) diff --git a/firmware/microblaze/apps/blinkenlights.c b/firmware/microblaze/apps/blinkenlights.c new file mode 100644 index 000000000..4cebe5c9d --- /dev/null +++ b/firmware/microblaze/apps/blinkenlights.c @@ -0,0 +1,26 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +#include "memory_map.h" +#include + +int main(int argc, char *argv[]) { + + uint32_t c = 0; + uint8_t i = 0; + + while(1) { + //delay(5000000); + for(c=0;c<5000000;c++) asm("NOP"); + output_regs->leds = (i++ % 2) ? 0xFF : 0x00; //blink everything on that register + } + + return 0; +} + +//void delay(uint32_t t) { +// while(t-- != 0) asm("NOP"); +//} diff --git a/firmware/microblaze/apps/cruft/Makefile.am b/firmware/microblaze/apps/cruft/Makefile.am new file mode 100644 index 000000000..a4f79935b --- /dev/null +++ b/firmware/microblaze/apps/cruft/Makefile.am @@ -0,0 +1,82 @@ +# +# Copyright 2010 Ettus Research LLC +# +# Copyright 2007,2008 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, see . +# + +include $(top_srcdir)/Makefile.common + +LDADD = $(top_srcdir)/lib/libu2fw.a + +AM_CFLAGS += -I$(top_srcdir)/../../host/lib/usrp + +noinst_PROGRAMS = txrx_uhd.elf + +# blink_leds \ +# blink_leds2 \ +# buf_ram_test \ +# burn_dbsrx_eeprom \ +# can_i_sub \ +# echo \ +# hello \ +# read_dbids \ +# set_hw_rev \ +# test1 \ +# test_db_spi \ +# test_i2c \ +# test_sd \ +# test_ram \ +# test_phy_comm \ +# test_lsadc \ +# test_lsdac \ +# timer_test \ +# txrx \ +# burnrev30 \ +# burnrev31 \ +# burnrev40 \ +# sd_gentest \ +# sd_bounce +# + +#nononono = \ +# eth_serdes \ +# gen_eth_packets \ +# rcv_eth_packets \ +# tx_standalone \ +# factory_test \ +# serdes_txrx \ +# mimo_tx \ +# mimo_tx_slave \ +# ibs_rx_test \ +# ibs_tx_test + +# tx_drop_SOURCES = tx_drop.c app_common.c +# tx_drop_rate_limited_SOURCES = tx_drop_rate_limited.c app_common.c +# tx_drop2_SOURCES = tx_drop2.c app_common.c +txrx_uhd_elf_SOURCES = txrx_uhd.c +# app_common_v2.c +#factory_test_SOURCES = factory_test.c app_common_v2.c +#eth_serdes_SOURCES = eth_serdes.c app_passthru_v2.c +#serdes_txrx_SOURCES = serdes_txrx.c app_common_v2.c +#mimo_tx_SOURCES = mimo_tx.c mimo_app_common_v2.c +#mimo_tx_slave_SOURCES = mimo_tx_slave.c app_common_v2.c + +#noinst_HEADERS = \ +# app_common_v2.h \ +# app_passthru_v2.h \ +# mimo_app_common_v2.h +# + diff --git a/firmware/microblaze/apps/cruft/app_passthru_v2.c b/firmware/microblaze/apps/cruft/app_passthru_v2.c new file mode 100644 index 000000000..406c56b3b --- /dev/null +++ b/firmware/microblaze/apps/cruft/app_passthru_v2.c @@ -0,0 +1,251 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app_passthru_v2.h" +#include "buffer_pool.h" +#include "memcpy_wa.h" +#include "ethernet.h" +#include "nonstdio.h" +#include "print_rmon_regs.h" +#include "db.h" +#include "clocks.h" +#include + +volatile bool link_is_up = false; // eth handler sets this + + +// If this is non-zero, this dbsm could be writing to the ethernet +dbsm_t *ac_could_be_sending_to_eth; + +//static unsigned char exp_seqno = 0; + +void +set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt) +{ + reply_pkt->ehdr.dst = cmd_pkt->ehdr.src; + reply_pkt->ehdr.src = *ethernet_mac_addr(); + reply_pkt->ehdr.ethertype = U2_ETHERTYPE; + reply_pkt->thdr.flags = 0; + reply_pkt->thdr.fifo_status = 0; // written by protocol engine + reply_pkt->thdr.seqno = 0; // written by protocol engine + reply_pkt->thdr.ack = 0; // written by protocol engine + u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN); + reply_pkt->fixed.timestamp = timer_regs->time; +} + +static void +send_reply(unsigned char *reply, size_t reply_len) +{ + if (reply_len < 64) + reply_len = 64; + + // wait for buffer to become idle + hal_set_leds(0x4, 0x4); + while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0) + ; + hal_set_leds(0x0, 0x4); + + // copy reply into CPU_TX_BUF + memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len); + + // wait until nobody else is sending to the ethernet + if (ac_could_be_sending_to_eth){ + hal_set_leds(0x8, 0x8); + dbsm_wait_for_opening(ac_could_be_sending_to_eth); + hal_set_leds(0x0, 0x8); + } + + // fire it off + bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, reply_len/4); + + // wait for it to complete (not long, it's a small pkt) + while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0) + ; + + bp_clear_buf(CPU_TX_BUF); +} + + +static size_t +op_id_cmd(const op_generic_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_id_reply_t *r = (op_id_reply_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) // no room + return 0; + + // Build reply subpacket + + r->opcode = OP_ID_REPLY; + r->len = sizeof(op_id_reply_t); + r->rid = p->rid; + r->addr = *ethernet_mac_addr(); + r->hw_rev = 0x0000; // FIXME + // r->fpga_md5sum = ; // FIXME + // r->sw_md5sum = ; // FIXME + + // FIXME Add d'board info, including dbid, min/max gain, min/max freq + + return r->len; +} + +static size_t +add_eop(void *reply_payload, size_t reply_payload_space) +{ + op_generic_t *r = (op_generic_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) + return 0; // no room + + r->opcode = OP_EOP; + r->len = sizeof(*r); + r->rid = 0; + r->ok = 0; + + return r->len; +} + +bool +handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len) +{ + unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4; + unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)]; + int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t); + + bool handled_it = false; + + // initialize reply + memset(reply, 0, sizeof(reply)); + set_reply_hdr((u2_eth_packet_t *) reply, pkt); + + // point to beginning of payload (subpackets) + unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t); + int payload_len = len - sizeof(u2_eth_packet_t); + + size_t subpktlen = 0; + + while (payload_len >= sizeof(op_generic_t)){ + const op_generic_t *gp = (const op_generic_t *) payload; + subpktlen = 0; + + switch(gp->opcode){ + case OP_EOP: // end of subpackets + goto end_of_subpackets; + + case OP_ID: + subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space); + handled_it = true; + break; + + default: + if (0){ + printf("\npassing on %d\n", gp->opcode); + } + break; + } + + int t = (gp->len + 3) & ~3; // bump to a multiple of 4 + payload += t; + payload_len -= t; + + subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4 + reply_payload += subpktlen; + reply_payload_space -= subpktlen; + } + + end_of_subpackets: + + if (handled_it){ + // add the EOP marker + subpktlen = add_eop(reply_payload, reply_payload_space); + subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4 + reply_payload += subpktlen; + reply_payload_space -= subpktlen; + + send_reply(reply, reply_payload - reply); + } + + return handled_it; +} + + +/* + * Called when an ethernet packet is received. + * Return true if we handled it here, otherwise + * it'll be passed on to the DSP Tx pipe + */ +bool +eth_pkt_inspector(dbsm_t *sm, int bufno) +{ + u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno); + size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4; + + //static size_t last_len = 0; + + // hal_toggle_leds(0x1); + + // inspect rcvd frame and figure out what do do. + + if (pkt->ehdr.ethertype != U2_ETHERTYPE) + return true; // ignore, probably bogus PAUSE frame from MAC + + int chan = u2p_chan(&pkt->fixed); + + switch (chan){ + case CONTROL_CHAN: + return handle_control_chan_frame(pkt, byte_len); + break; + + case 0: + default: +#if 0 + if (last_len != 0){ + if (byte_len != last_len){ + printf("Len: %d last: %d\n", byte_len, last_len); + } + } + last_len = byte_len; + + if((pkt->thdr.seqno) == exp_seqno){ + exp_seqno++; + //putchar('.'); + } + else { + // putchar('S'); + //printf("S%d %d ",exp_seqno,pkt->thdr.seqno); + exp_seqno = pkt->thdr.seqno + 1; + } +#endif + return false; // pass it on to Tx DSP + break; + } +} + +/* + * Called when eth phy state changes (w/ interrupts disabled) + */ +void +link_changed_callback(int speed) +{ + link_is_up = speed != 0; + hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45); + printf("\neth link changed: speed = %d\n", speed); +} diff --git a/firmware/microblaze/apps/cruft/app_passthru_v2.h b/firmware/microblaze/apps/cruft/app_passthru_v2.h new file mode 100644 index 000000000..3904c670f --- /dev/null +++ b/firmware/microblaze/apps/cruft/app_passthru_v2.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008 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, see . + */ + +#ifndef INCLUDED_APP_COMMON_H +#define INCLUDED_APP_COMMON_H + +#include +#include "usrp2_eth_packet.h" +#include "dbsm.h" +#include "memory_map.h" +#include "hal_io.h" +#include +#include + +#define CPU_TX_BUF 7 // cpu -> eth + +#define _AL4 __attribute__((aligned (4))) + +extern volatile bool link_is_up; // eth handler sets this + + +// If there's a dbsm that sends to the ethernet, put it's address here +extern dbsm_t *ac_could_be_sending_to_eth; + + +void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt); + +/* + * Called when an ethernet packet is received. + * Return true if we handled it here, otherwise + * it'll be passed on to the DSP Tx pipe + */ +bool eth_pkt_inspector(dbsm_t *sm, int bufno); + +void link_changed_callback(int speed); + +bool handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len); + +#endif /* INCLUDED_APP_COMMON_H */ diff --git a/firmware/microblaze/apps/cruft/blink_leds.c b/firmware/microblaze/apps/cruft/blink_leds.c new file mode 100644 index 000000000..682ca8db2 --- /dev/null +++ b/firmware/microblaze/apps/cruft/blink_leds.c @@ -0,0 +1,40 @@ +/* + * Copyright 2007 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "hal_io.h" +#include "nonstdio.h" + +int +main(void) +{ + int counter = 0; + + u2_init(); + + putstr("blink_leds\n"); + while(1){ + output_regs->leds = (counter++ & 0x3); + } + + return 0; +} diff --git a/firmware/microblaze/apps/cruft/blink_leds2.c b/firmware/microblaze/apps/cruft/blink_leds2.c new file mode 100644 index 000000000..13e78afb3 --- /dev/null +++ b/firmware/microblaze/apps/cruft/blink_leds2.c @@ -0,0 +1,53 @@ +/* + * Copyright 2007 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "hal_io.h" +#include "pic.h" +#include "nonstdio.h" + +//#define DELTA_T (MASTER_CLK_RATE/2) // 0.5s (10ns per tick) +#define DELTA_T 5000 // 5 us (10ns per tick) + + +void +timer_handler(unsigned irq) +{ + hal_set_timeout(DELTA_T); // schedule next timeout + hal_toggle_leds(0x2); +} + +int +main(void) +{ + u2_init(); + + putstr("blink_leds2\n"); + pic_register_handler(IRQ_ONETIME, timer_handler); + hal_set_timeout(DELTA_T); // schedule next timeout + + while(1){ + hal_toggle_leds(0x1); + } + + return 0; +} diff --git a/firmware/microblaze/apps/cruft/buf_ram_test.c b/firmware/microblaze/apps/cruft/buf_ram_test.c new file mode 100644 index 000000000..1aca2aec5 --- /dev/null +++ b/firmware/microblaze/apps/cruft/buf_ram_test.c @@ -0,0 +1,89 @@ +/* + * Copyright 2007 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, see . + */ + +#include "u2_init.h" +#include "memory_map.h" +#include +#include "nonstdio.h" +#include "hal_io.h" +#include "mdelay.h" + + +static void +write_bufs(void) +{ + int i, n; + int counter = 0; + + for (n = 0; n < NBUFFERS; n++){ + volatile int *p = buffer_ram(n); + for (i = 0; i < BP_NLINES; i++) + p[i] = counter++; + } +} + +// return number of errors detected +static int +check_bufs(void) +{ + int i, n; + int counter = 0; + int nerrors = 0; + + for (n = 0; n < NBUFFERS; n++){ + volatile int *p = buffer_ram(n); + for (i = 0; i < BP_NLINES; i++, counter++){ + int rd = p[i]; + if (rd != counter){ + putchar('b'); + putchar(n + '0'); + putchar('['); + puthex16(i); + putstr("] exp: "); + puthex32(counter); + putstr(" got: "); + puthex32_nl(rd); + nerrors++; + } + } + } + return nerrors; +} + + +int +main(void) +{ + u2_init(); + + output_regs->leds = 0; + + write_bufs(); + int nerrors = check_bufs(); + + if (nerrors == 0){ + output_regs->leds = 0x3; // leds on -> PASS + putstr("PASS\n"); + } + else { + output_regs->leds = 0x0; // leds off -> FAIL + putstr("FAIL\n"); + } + + hal_finish(); + return 0; +} diff --git a/firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c b/firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c new file mode 100644 index 000000000..116d4d8d0 --- /dev/null +++ b/firmware/microblaze/apps/cruft/burn_dbsrx_eeprom.c @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "i2c.h" +#include "usrp2_i2c_addr.h" +#include "mdelay.h" +#include "hal_io.h" +#include "nonstdio.h" +#include + + + +int read_dboard_eeprom(int i2c_addr); + + +#define USRP_DBID_DBS_RX 0x0002 +#define USRP_DBID_DBS_RX_WITH_CLOCK_MOD 0x000d + +const char dbs_rx_rev2_eeprom[] = { + 0xdb, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18 +}; + +#define LED_VALS (LED_A | LED_B | LED_C | LED_D) +#define LED_MASK (LED_A | LED_B | LED_C | LED_D) + +int +main(void) +{ + u2_init(); + + puts("\nburn_dbsrx_eeprom\n"); + + hal_set_leds(0, ~0); // all off + + int i2c_addr = I2C_ADDR_RX_A; + int dbid = read_dboard_eeprom(i2c_addr); + bool ok; + const char *msg = 0; + + switch (dbid){ + case -1: + msg = "No RX daughterboard found"; + goto bad; + + case -2: + msg = "Invalid RX EEPROM contents"; + goto bad; + + case USRP_DBID_DBS_RX_WITH_CLOCK_MOD: + msg = "RX Daughterboard already reports being a DBS RX w/ CLOCK_MOD"; + goto good; + + case USRP_DBID_DBS_RX: + // Says it's a DBS_RX, attempt to burn the EEPROM + ok = eeprom_write(i2c_addr, 0, + dbs_rx_rev2_eeprom, sizeof(dbs_rx_rev2_eeprom)); + if (ok){ + msg = "Successfully programmed db as DBS RX Rev 2.1"; + goto good; + } + else { + msg = "Failed to write daugherboard eeprom"; + goto bad; + } + + default: + msg = "Daughterboard is not a DBS RX; ignored"; + goto bad; + } + + good: + puts(msg); + hal_set_leds(LED_VALS, LED_MASK); + while (1) + ; + + bad: + puts(msg); + while(1){ + hal_toggle_leds(LED_VALS); + mdelay(50); + } +} diff --git a/firmware/microblaze/apps/cruft/burnrev30.c b/firmware/microblaze/apps/cruft/burnrev30.c new file mode 100644 index 000000000..40fa53e34 --- /dev/null +++ b/firmware/microblaze/apps/cruft/burnrev30.c @@ -0,0 +1,162 @@ +/* + * Copyright 2007,2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "dbsm.h" +#include "app_common_v2.h" +#include "memcpy_wa.h" +#include +#include +#include +#include +#include +#include +#include "sd.h" +#include "mdelay.h" + +#define HW_REV_MAJOR 3 +#define HW_REV_MINOR 0 + +int test_ram() +{ + int i,j,k; + output_regs->ram_page = 1<<10; + + extram[0] = 0xDEADBEEF; + extram[1] = 0xF00D1234; + extram[7] = 0x76543210; + + output_regs->ram_page = 2<<10; + extram[7] = 0x55555555; + extram[1] = 0xaaaaaaaa; + extram[0] = 0xeeeeeeee; + + output_regs->ram_page = 1<<10; + + i = extram[0]; + k = extram[1]; + j = extram[7]; + + if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { + puts("RAM FAIL1!\n"); + puthex32_nl(i); + puthex32_nl(j); + puthex32_nl(k); + return 0; + } + + output_regs->ram_page = 2<<10; + + j = extram[7]; + k = extram[1]; + i = extram[0]; + + if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { + puts("RAM FAIL2!\n"); + puthex32_nl(i); + puthex32_nl(j); + puthex32_nl(k); + return 0; + } + return 1; +} + +int test_sd() +{ + int i = sd_init(); + if(i==0) { + puts("FAILED INIT of Card\n"); + return 0; + } + + unsigned char buf[512]; + i = sd_read_block(2048,buf); + if(i == 0) { + puts("READ Command Rejected\n"); + return 0; + } + if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50)) + ; + else { + puts("Read bad data from SD Card\n"); + return 0; + } + return 1; +} + +int +main(void) +{ + u2_init(); + + putstr("\nFactory Test, Board Rev 3.0\n"); + + bool ok = true; + unsigned char maj = HW_REV_MAJOR; + unsigned char min = HW_REV_MINOR; + ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1); + ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1); + + putstr("\nset_hw_rev\n"); + if (ok) + printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); + else { + printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); + hal_finish(); + return 0; + } + + if(test_sd()) + puts("SD OK\n"); + else { + puts("SD FAIL\n"); + //hal_finish(); + //return 0; + } + if(test_ram()) + puts("RAM OK\n"); + else { + puts("RAM FAIL\n"); + hal_finish(); + return 0; + } + + print_mac_addr(ethernet_mac_addr()->addr); + newline(); + + clocks_mimo_config(MC_WE_LOCK_TO_SMA); + + while (!clocks_lock_detect()) { + puts("No Lock"); + mdelay(1000); + } + puts("Clock Locked\n"); + +} diff --git a/firmware/microblaze/apps/cruft/burnrev31.c b/firmware/microblaze/apps/cruft/burnrev31.c new file mode 100644 index 000000000..f6b08d187 --- /dev/null +++ b/firmware/microblaze/apps/cruft/burnrev31.c @@ -0,0 +1,162 @@ +/* + * Copyright 2007,2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "dbsm.h" +#include "app_common_v2.h" +#include "memcpy_wa.h" +#include +#include +#include +#include +#include +#include +#include "sd.h" +#include "mdelay.h" + +#define HW_REV_MAJOR 3 +#define HW_REV_MINOR 1 + +int test_ram() +{ + int i,j,k; + output_regs->ram_page = 1<<10; + + extram[0] = 0xDEADBEEF; + extram[1] = 0xF00D1234; + extram[7] = 0x76543210; + + output_regs->ram_page = 2<<10; + extram[7] = 0x55555555; + extram[1] = 0xaaaaaaaa; + extram[0] = 0xeeeeeeee; + + output_regs->ram_page = 1<<10; + + i = extram[0]; + k = extram[1]; + j = extram[7]; + + if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { + puts("RAM FAIL1!\n"); + puthex32_nl(i); + puthex32_nl(j); + puthex32_nl(k); + return 0; + } + + output_regs->ram_page = 2<<10; + + j = extram[7]; + k = extram[1]; + i = extram[0]; + + if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { + puts("RAM FAIL2!\n"); + puthex32_nl(i); + puthex32_nl(j); + puthex32_nl(k); + return 0; + } + return 1; +} + +int test_sd() +{ + int i = sd_init(); + if(i==0) { + puts("FAILED INIT of Card\n"); + return 0; + } + + unsigned char buf[512]; + i = sd_read_block(2048,buf); + if(i == 0) { + puts("READ Command Rejected\n"); + return 0; + } + if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50)) + ; + else { + puts("Read bad data from SD Card\n"); + return 0; + } + return 1; +} + +int +main(void) +{ + u2_init(); + + putstr("\nFactory Test, Board Rev 3.1\n"); + + bool ok = true; + unsigned char maj = HW_REV_MAJOR; + unsigned char min = HW_REV_MINOR; + ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1); + ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1); + + putstr("\nset_hw_rev\n"); + if (ok) + printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); + else { + printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); + hal_finish(); + return 0; + } + + if(test_sd()) + puts("SD OK\n"); + else { + puts("SD FAIL\n"); + //hal_finish(); + //return 0; + } + if(test_ram()) + puts("RAM OK\n"); + else { + puts("RAM FAIL\n"); + hal_finish(); + return 0; + } + + print_mac_addr(ethernet_mac_addr()->addr); + newline(); + + clocks_mimo_config(MC_WE_LOCK_TO_SMA); + + while (!clocks_lock_detect()) { + puts("No Lock"); + mdelay(1000); + } + puts("Clock Locked\n"); + +} diff --git a/firmware/microblaze/apps/cruft/can_i_sub.c b/firmware/microblaze/apps/cruft/can_i_sub.c new file mode 100644 index 000000000..ed49791f0 --- /dev/null +++ b/firmware/microblaze/apps/cruft/can_i_sub.c @@ -0,0 +1,25 @@ +#include +#include + +//typedef long long int64_t; + + +int64_t sub(int64_t a, int64_t b); +void print(int64_t d); + +int main(void) +{ + u2_init(); + + int64_t d = sub(462550990848000LL, 462028800000000LL); + print_uint64(d); + newline(); + return 0; +} + +int64_t sub(int64_t a, int64_t b) +{ + return a - b; +} + + diff --git a/firmware/microblaze/apps/cruft/double_buffer_fragment.c b/firmware/microblaze/apps/cruft/double_buffer_fragment.c new file mode 100644 index 000000000..cfc061247 --- /dev/null +++ b/firmware/microblaze/apps/cruft/double_buffer_fragment.c @@ -0,0 +1,138 @@ +#if 0 +void +double_buffering(int port) { + unsigned int localstatus = buffer_pool_status->status; + + if(localstatus & BPS_DONE_0) { + bp_clear_buf(0); + if(buffer_state[0] == FILLING) { + buffer_state[0] = FULL; + if(buffer_state[1] == EMPTY) { + bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines + buffer_state[1] = FILLING; + } + else + dsp_rx_idle = 1; + if(serdes_tx_idle) { + serdes_tx_idle = 0; + bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0 + buffer_state[0] = EMPTYING; + } + } + else { // buffer was emptying + buffer_state[0] = EMPTY; + if(dsp_rx_idle) { + dsp_rx_idle = 0; + bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines + buffer_state[0] = FILLING; + } + if(buffer_state[1] == FULL) { + bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1 + buffer_state[1] = EMPTYING; + } + else + serdes_tx_idle = 1; + } + putstr("Int Proc'ed 0\n"); + } + + if(localstatus & BPS_DONE_1) { + bp_clear_buf(1); + if(buffer_state[1] == FILLING) { + buffer_state[1] = FULL; + if(buffer_state[0] == EMPTY) { + bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines + buffer_state[0] = FILLING; + } + else + dsp_rx_idle = 1; + if(serdes_tx_idle) { + serdes_tx_idle = 0; + bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1 + buffer_state[1] = EMPTYING; + } + } + else { // buffer was emptying + buffer_state[1] = EMPTY; + if(dsp_rx_idle) { + dsp_rx_idle = 0; + bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines + buffer_state[1] = FILLING; + } + if(buffer_state[0] == FULL) { + bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0 + buffer_state[0] = EMPTYING; + } + else + serdes_tx_idle = 1; + } + putstr("Int Proc'ed 1\n"); + } + + if(localstatus & BPS_DONE_2) { + bp_clear_buf(2); + if(buffer_state[2] == FILLING) { + buffer_state[2] = FULL; + if(buffer_state[3] == EMPTY) { + bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3, use 500 lines + buffer_state[3] = FILLING; + } + else + serdes_rx_idle = 1; + if(dsp_tx_idle) { + dsp_tx_idle = 0; + bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2 + buffer_state[2] = EMPTYING; + } + } + else { // buffer was emptying + buffer_state[2] = EMPTY; + if(serdes_rx_idle) { + serdes_rx_idle = 0; + bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2 + buffer_state[2] = FILLING; + } + if(buffer_state[3] == FULL) { + bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3 + buffer_state[3] = EMPTYING; + } + else + dsp_tx_idle = 1; + } + putstr("Int Proc'ed 2\n"); + } + + if(localstatus & BPS_DONE_3) { + bp_clear_buf(3); + if(buffer_state[3] == FILLING) { + buffer_state[3] = FULL; + if(buffer_state[2] == EMPTY) { + bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2, use 500 lines + buffer_state[2] = FILLING; + } + else + serdes_rx_idle = 1; + if(dsp_tx_idle) { + dsp_tx_idle = 0; + bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3 + buffer_state[3] = EMPTYING; + } + } + else { // buffer was emptying + buffer_state[3] = EMPTY; + if(serdes_rx_idle) { + serdes_rx_idle = 0; + bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3 + buffer_state[3] = FILLING; + } + if(buffer_state[2] == FULL) { + bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2 + buffer_state[2] = EMPTYING; + } + else + dsp_tx_idle = 1; + } + putstr("Int Proc'ed 3\n"); + } +} +#endif diff --git a/firmware/microblaze/apps/cruft/echo.c b/firmware/microblaze/apps/cruft/echo.c new file mode 100644 index 000000000..89108ee80 --- /dev/null +++ b/firmware/microblaze/apps/cruft/echo.c @@ -0,0 +1,34 @@ +/* + * Copyright 2008 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, see . + */ + +#include "u2_init.h" +#include "stdio.h" + +int +main(void) +{ + u2_init(); + + puts("\n>>> echo <<<"); + + while (1){ + int ch = getchar(); + putchar(ch); + } + + return 0; +} diff --git a/firmware/microblaze/apps/cruft/eth_serdes.c b/firmware/microblaze/apps/cruft/eth_serdes.c new file mode 100644 index 000000000..2d2ddc1ca --- /dev/null +++ b/firmware/microblaze/apps/cruft/eth_serdes.c @@ -0,0 +1,233 @@ +/* + * Copyright 2007,2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "dbsm.h" +#include "app_passthru_v2.h" +#include "memcpy_wa.h" +#include "clocks.h" +#include +#include +#include + + +#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) + +#if (FW_SETS_SEQNO) +static int fw_seqno __attribute__((unused)); // used when f/w is filling in sequence numbers +#endif + + +/* + * Full duplex Tx and Rx between ethernet and serdes + * + * Buffer 1 is used by the cpu to send frames to the host. + * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow + * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow + */ +//#define CPU_RX_BUF 0 // eth -> cpu + +#define DSP_RX_BUF_0 2 // serdes -> eth (double buffer) +#define DSP_RX_BUF_1 3 // serdes -> eth +#define DSP_TX_BUF_0 4 // eth -> serdes (double buffer) +#define DSP_TX_BUF_1 5 // eth -> serdes + +/* + * ================================================================ + * configure serdes double buffering state machine (eth -> serdes) + * ================================================================ + */ + + +// Receive from ethernet +buf_cmd_args_t dsp_tx_recv_args = { + PORT_ETH, + 0, + BP_LAST_LINE +}; + +// send to serdes +buf_cmd_args_t dsp_tx_send_args = { + PORT_SERDES, + 0, + 0 // filled in from last_line register +}; + +dbsm_t dsp_tx_sm; // the state machine + +/* + * ==================================================================== + * configure serdes RX double buffering state machine (serdes -> eth) + * ==================================================================== + */ + +// receive from serdes +buf_cmd_args_t dsp_rx_recv_args = { + PORT_SERDES, + 0, + BP_LAST_LINE +}; + +// send to ETH +buf_cmd_args_t dsp_rx_send_args = { + PORT_ETH, + 0, // starts with ethernet header in line 0 + 0, // filled in from list_line register +}; + +dbsm_t dsp_rx_sm; // the state machine + + +// The mac address of the host we're sending to. +eth_mac_addr_t host_mac_addr; + + +// ---------------------------------------------------------------- + + +#if (FW_SETS_SEQNO) +/* + * Debugging ONLY. This will be handled by the tx_protocol_engine. + * + * This is called when the DSP Rx chain has filled in a packet. + * We set and increment the seqno, then return false, indicating + * that we didn't handle the packet. A bit of a kludge + * but it should work. + */ + +bool +fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false +{ +#if 0 + uint32_t *p = buffer_ram(buf_this); + uint32_t last_line = buffer_pool_status->last_line[buf_this] - sm->last_line_adj; + printf("fw_sets_seqno_inspector: buf_this = %d, last_line = %d\n", + buf_this, last_line); + + print_buffer(p, (last_line + 1)); +#endif + +#if 0 + uint32_t *p = buffer_ram(buf_this); + uint32_t seqno = fw_seqno++; + + // KLUDGE all kinds of nasty magic numbers and embedded knowledge + uint32_t t = p[4]; + t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); + p[4] = t; +#endif + + return false; // we didn't handle the packet +} +#endif + + +inline static void +buffer_irq_handler(unsigned irq) +{ + uint32_t status = buffer_pool_status->status; + + if (0 && (status & ~BPS_IDLE_ALL)){ + putstr("status = "); + puthex32_nl(status); + } + + dbsm_process_status(&dsp_tx_sm, status); + dbsm_process_status(&dsp_rx_sm, status); +} + +int +main(void) +{ + u2_init(); + + output_regs->led_src = 0x3; // h/w controls bottom two bits + clocks_enable_test_clk(true, 1); + + putstr("\neth <-> serdes\n"); + + ethernet_register_link_changed_callback(link_changed_callback); + ethernet_init(); + + // clocks_mimo_config(MC_WE_LOCK_TO_SMA | MC_PROVIDE_CLK_TO_MIMO); + clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO); + +#if 0 + // make bit 15 of Tx gpio's be a s/w output + hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); + hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); +#endif + +#if 1 + output_regs->debug_mux_ctrl = 1; + hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); + hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); +#endif + + + // initialize double buffering state machine for ethernet -> serdes + + dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, + &dsp_tx_recv_args, &dsp_tx_send_args, + eth_pkt_inspector); + + + // initialize double buffering state machine for serdes -> ethernet + + if (FW_SETS_SEQNO){ + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + fw_sets_seqno_inspector); + } + else { + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + dbsm_nop_inspector); + } + + // tell app_common that this dbsm could be sending to the ethernet + ac_could_be_sending_to_eth = &dsp_rx_sm; + + + // kick off the state machines + dbsm_start(&dsp_tx_sm); + dbsm_start(&dsp_rx_sm); + + //int which = 0; + + while(1){ + // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); + // which ^= 0x8000; + + buffer_irq_handler(0); + } +} diff --git a/firmware/microblaze/apps/cruft/factory_test.c b/firmware/microblaze/apps/cruft/factory_test.c new file mode 100644 index 000000000..e1fbb0e40 --- /dev/null +++ b/firmware/microblaze/apps/cruft/factory_test.c @@ -0,0 +1,438 @@ +/* + * Copyright 2007,2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "dbsm.h" +#include "app_common_v2.h" +#include "memcpy_wa.h" +#include +#include +#include +#include +#include +#include +#include "sd.h" + +#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) + +#if (FW_SETS_SEQNO) +static int fw_seqno; // used when f/w is filling in sequence numbers +#endif + + +/* + * Full duplex Tx and Rx between ethernet and DSP pipelines + * + * Buffer 1 is used by the cpu to send frames to the host. + * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow + * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow + */ +//#define CPU_RX_BUF 0 // eth -> cpu + +#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer) +#define DSP_RX_BUF_1 3 // dsp rx -> eth +#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer) +#define DSP_TX_BUF_1 5 // eth -> dsp tx + +/* + * ================================================================ + * configure DSP TX double buffering state machine (eth -> dsp) + * ================================================================ + */ + +// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) +// DSP Tx reads word0 (flags) + timestamp followed by samples + +#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) + +// Receive from ethernet +buf_cmd_args_t dsp_tx_recv_args = { + PORT_ETH, + 0, + BP_LAST_LINE +}; + +// send to DSP Tx +buf_cmd_args_t dsp_tx_send_args = { + PORT_DSP, + DSP_TX_FIRST_LINE, // starts just past transport header + 0 // filled in from last_line register +}; + +dbsm_t dsp_tx_sm; // the state machine + +/* + * ================================================================ + * configure DSP RX double buffering state machine (dsp -> eth) + * ================================================================ + */ + +// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0) +// DSP Rx writes timestamp followed by nlines_per_frame of samples +#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1) + +// receive from DSP +buf_cmd_args_t dsp_rx_recv_args = { + PORT_DSP, + DSP_RX_FIRST_LINE, + BP_LAST_LINE +}; + +// send to ETH +buf_cmd_args_t dsp_rx_send_args = { + PORT_ETH, + 0, // starts with ethernet header in line 0 + 0, // filled in from list_line register +}; + +dbsm_t dsp_rx_sm; // the state machine + + +// The mac address of the host we're sending to. +eth_mac_addr_t host_mac_addr; + + +// variables for streaming mode + +static bool streaming_p = false; +static unsigned int streaming_items_per_frame = 0; +static int streaming_frame_count = 0; +#define FRAMES_PER_CMD 1000 + +bool is_streaming(void){ return streaming_p; } + +// ---------------------------------------------------------------- + + +void +restart_streaming(void) +{ + // setup RX DSP regs + dsp_rx_regs->clear_state = 1; // reset + + streaming_p = true; + streaming_frame_count = FRAMES_PER_CMD; + + dsp_rx_regs->rx_command = + MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, + streaming_items_per_frame, + 1, 1); // set "chain" bit + + // kick off the state machine + dbsm_start(&dsp_rx_sm); + + dsp_rx_regs->rx_time = 0; // enqueue first of two commands + + // make sure this one and the rest have the "now" and "chain" bits set. + dsp_rx_regs->rx_command = + MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, + streaming_items_per_frame, + 1, 1); + + dsp_rx_regs->rx_time = 0; // enqueue second command +} + +void +start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p) +{ + host_mac_addr = *host; // remember who we're sending to + + /* + * Construct ethernet header and word0 and preload into two buffers + */ + u2_eth_packet_t pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.ehdr.dst = *host; + pkt.ehdr.src = *ethernet_mac_addr(); + pkt.ehdr.ethertype = U2_ETHERTYPE; + u2p_set_word0(&pkt.fixed, 0, 0); + // DSP RX will fill in timestamp + + memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt)); + memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt)); + + + if (FW_SETS_SEQNO) + fw_seqno = 0; + + streaming_items_per_frame = p->items_per_frame; + restart_streaming(); +} + + +void +stop_rx_cmd(void) +{ + streaming_p = false; + dsp_rx_regs->clear_state = 1; // flush cmd queue + bp_clear_buf(DSP_RX_BUF_0); + bp_clear_buf(DSP_RX_BUF_1); +} + + +static void +setup_tx() +{ + dsp_tx_regs->clear_state = 1; + bp_clear_buf(DSP_TX_BUF_0); + bp_clear_buf(DSP_TX_BUF_1); + + int tx_scale = 256; + int interp = 32; + + // setup some defaults + + dsp_tx_regs->freq = 0; + dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; + dsp_tx_regs->interp_rate = interp; +} + + +#if (FW_SETS_SEQNO) +/* + * Debugging ONLY. This will be handled by the tx_protocol_engine. + * + * This is called when the DSP Rx chain has filled in a packet. + * We set and increment the seqno, then return false, indicating + * that we didn't handle the packet. A bit of a kludge + * but it should work. + */ +bool +fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false +{ + uint32_t *p = buffer_ram(buf_this); + uint32_t seqno = fw_seqno++; + + // KLUDGE all kinds of nasty magic numbers and embedded knowledge + uint32_t t = p[4]; + t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); + p[4] = t; + + // queue up another rx command when required + if (streaming_p && --streaming_frame_count == 0){ + streaming_frame_count = FRAMES_PER_CMD; + dsp_rx_regs->rx_time = 0; + } + + return false; // we didn't handle the packet +} +#endif + + +inline static void +buffer_irq_handler(unsigned irq) +{ + uint32_t status = buffer_pool_status->status; + + dbsm_process_status(&dsp_tx_sm, status); + dbsm_process_status(&dsp_rx_sm, status); +} + +int test_ram() +{ + int i,j,k; + output_regs->ram_page = 1<<10; + + extram[0] = 0xDEADBEEF; + extram[1] = 0xF00D1234; + extram[7] = 0x76543210; + + output_regs->ram_page = 2<<10; + extram[7] = 0x55555555; + extram[1] = 0xaaaaaaaa; + extram[0] = 0xeeeeeeee; + + output_regs->ram_page = 1<<10; + + i = extram[0]; + k = extram[1]; + j = extram[7]; + + if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { + puts("RAM FAIL1!\n"); + puthex32_nl(i); + puthex32_nl(j); + puthex32_nl(k); + return 0; + } + + output_regs->ram_page = 2<<10; + + j = extram[7]; + k = extram[1]; + i = extram[0]; + + if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { + puts("RAM FAIL2!\n"); + puthex32_nl(i); + puthex32_nl(j); + puthex32_nl(k); + return 0; + } + return 1; +} + +int test_sd() +{ + int i = sd_init(); + if(i==0) { + puts("FAILED INIT of Card\n"); + return 0; + } + + unsigned char buf[512]; + i = sd_read_block(2048,buf); + if(i == 0) { + puts("READ Command Rejected\n"); + return 0; + } + if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50)) + ; + else { + puts("Read bad data from SD Card\n"); + return 0; + } + return 1; +} + +int +main(void) +{ + u2_init(); + + putstr("\nFactory Test\n"); + + print_mac_addr(ethernet_mac_addr()->addr); + newline(); + + if(test_sd()) + puts("SD OK\n"); + else { + puts("SD FAIL\n"); + // hal_finish(); + //return 0; + } + if(test_ram()) + puts("RAM OK\n"); + else { + puts("RAM FAIL\n"); + hal_finish(); + return 0; + } + + print_mac_addr(ethernet_mac_addr()->addr); + newline(); + + output_regs->led_src = 0x7; // make bottom 3 controlled by HW + + ethernet_register_link_changed_callback(link_changed_callback); + ethernet_init(); + + clocks_enable_tx_dboard(true,1); + clocks_mimo_config(MC_WE_LOCK_TO_SMA); +#if 0 + // make bit 15 of Tx gpio's be a s/w output + hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); + hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); +#endif + + output_regs->debug_mux_ctrl = 1; +#if 0 + hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); + hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); +#endif + + + // initialize double buffering state machine for ethernet -> DSP Tx + + dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, + &dsp_tx_recv_args, &dsp_tx_send_args, + eth_pkt_inspector); + + + // initialize double buffering state machine for DSP RX -> Ethernet + + if (FW_SETS_SEQNO){ + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + fw_sets_seqno_inspector); + } + else { + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + dbsm_nop_inspector); + } + + // tell app_common that this dbsm could be sending to the ethernet + ac_could_be_sending_to_eth = &dsp_rx_sm; + + + // program tx registers + setup_tx(); + + // kick off the state machine + dbsm_start(&dsp_tx_sm); + + //int which = 0; + + while(1){ + // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); + // which ^= 0x8000; + + buffer_irq_handler(0); + + int pending = pic_regs->pending; // poll for under or overrun + + if (pending & PIC_UNDERRUN_INT){ + dbsm_handle_tx_underrun(&dsp_tx_sm); + pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt + putchar('U'); + } + + if (pending & PIC_OVERRUN_INT){ + dbsm_handle_rx_overrun(&dsp_rx_sm); + pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt + + // FIXME Figure out how to handle this robustly. + // Any buffers that are emptying should be allowed to drain... + + if (streaming_p){ + // restart_streaming(); + // FIXME report error + } + else { + // FIXME report error + } + putchar('O'); + } + } +} diff --git a/firmware/microblaze/apps/cruft/gen_eth_packets.c b/firmware/microblaze/apps/cruft/gen_eth_packets.c new file mode 100644 index 000000000..4d521f6bf --- /dev/null +++ b/firmware/microblaze/apps/cruft/gen_eth_packets.c @@ -0,0 +1,187 @@ +/* + * Copyright 2007 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "memcpy_wa.h" +#include "print_rmon_regs.h" +#include +#include +#include + + +// ---------------------------------------------------------------- + +static eth_mac_addr_t dst_mac_addr = + {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}; + +// ---------------------------------------------------------------- + +// #define PACKET_SIZE 1500 // bytes +// #define ETH_DATA_RATE 1000000 // 1MB/s +// #define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s + +// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE; // ticks between interrupts + +static int timer_delta = (int)(MASTER_CLK_RATE * 1e-3); // tick at 1 kHz +static int sim_timer_delta = (int)(MASTER_CLK_RATE * 100e-6); // tick at 10 kHz + +static volatile bool send_packet_now = false; // timer handler sets this +static volatile bool link_is_up = false; // eth handler sets this + +int packet_number = 0; + + +#define CPU_TX_BUF 0 // cpu xmits ethernet frames from here +#define CPU_RX_BUF 1 // receive ethernet frames here + +// ---------------------------------------------------------------- + +/* + * Called when eth phy state changes (w/ interrupts disabled) + */ +void +link_changed_callback(int speed) +{ + link_is_up = speed == 0 ? false : true; + hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2); + printf("\neth link changed: speed = %d\n", speed); +} + +void +timer_irq_handler(unsigned irq) +{ + hal_set_timeout(timer_delta); // schedule next timeout + send_packet_now = 1; +} + + +static void +init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum) +{ + int i = 0; + int mark = ((bufnum & 0xff) << 24) | 0x005A0000; + + for (i = 0; i < BP_NLINES; i++){ + buf[i] = mark | i; + mark ^= 0x00FF0000; + } + + // copy header into buffer + memcpy_wa(buf, pkt, sizeof(*pkt)); +} + +static void +init_packets(void) +{ + u2_eth_packet_t pkt __attribute__((aligned (4))); + + memset(&pkt, 0, sizeof(pkt)); + + pkt.ehdr.dst = dst_mac_addr; + pkt.ehdr.src = *ethernet_mac_addr(); + pkt.ehdr.ethertype = U2_ETHERTYPE; + pkt.fixed.word0 = 0x01234567; + pkt.fixed.timestamp = 0xffffffff; + + // init just the one we're using + init_packet((void *)buffer_ram(CPU_TX_BUF), &pkt, CPU_TX_BUF); +} + +int +main(void) +{ + int npackets_sent = 0; + + u2_init(); + + // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output + //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + + putstr("\ngen_eth_packets\n"); + + hal_set_leds(0x0, 0x3); + + init_packets(); + + pic_register_handler(IRQ_TIMER, timer_irq_handler); + + if (hwconfig_simulation_p()) + timer_delta = sim_timer_delta; + + hal_set_timeout(timer_delta); + + ethernet_register_link_changed_callback(link_changed_callback); + ethernet_init(); + + /* + if (hwconfig_simulation_p()){ + eth_mac->speed = 4; // hardcode mac speed to 1000 + link_is_up = true; + } + */ + + // fire off a receive from the ethernet + bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE); + + while(1){ + uint32_t status = buffer_pool_status->status; + + if (status & (BPS_DONE(CPU_RX_BUF) | BPS_ERROR(CPU_RX_BUF))){ + bp_clear_buf(CPU_RX_BUF); + // ignore incoming ethernet packets; they were looped back in sim + bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE); + } + + if (status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))){ + if (status & BPS_ERROR(CPU_TX_BUF)){ + putchar('E'); + } + bp_clear_buf(CPU_TX_BUF); + npackets_sent++; + if ((npackets_sent & 0xF) == 0){ // print after every 16 packets + //print_rmon_regs(); + putchar('.'); + } + } + + if (link_is_up && send_packet_now && (status & BPS_IDLE(CPU_TX_BUF))){ + send_packet_now = false; + + // kick off the next packet + // FIXME set packet number in packet + + bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, 255); // 1KB total + hal_toggle_leds(0x1); + } + } + + hal_finish(); + return 1; +} diff --git a/firmware/microblaze/apps/cruft/gen_pause_frames.c b/firmware/microblaze/apps/cruft/gen_pause_frames.c new file mode 100644 index 000000000..0f81dafff --- /dev/null +++ b/firmware/microblaze/apps/cruft/gen_pause_frames.c @@ -0,0 +1,207 @@ +/* + * Copyright 2007 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, see . + */ + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "u2_eth_packet.h" +#include "memcpy_wa.h" +#include +#include + + +// ---------------------------------------------------------------- + +unsigned char dst_mac_addr[6] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +// ---------------------------------------------------------------- + +// #define PACKET_SIZE 1500 // bytes +// #define ETH_DATA_RATE 1000000 // 1MB/s +// #define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s + +// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE; // ticks between interrupts + +static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz + +static volatile bool send_packet_now = false; // timer handler sets this +static volatile bool link_is_up = false; // eth handler sets this + +int packet_number = 0; + +// ---------------------------------------------------------------- + +// debugging output on tx pins +#define LS_MASK 0xE0000 +#define LS_1000 0x80000 +#define LS_100 0x40000 +#define LS_10 0x20000 + + +/* + * Called when eth phy state changes (w/ interrupts disabled) + */ +void +link_changed_callback(int speed) +{ + int v = 0; + switch(speed){ + case 10: + v = LS_10; + link_is_up = true; + break; + + case 100: + v = LS_100; + link_is_up = true; + break; + + case 1000: + v = LS_100; + link_is_up = true; + break; + + default: + v = 0; + link_is_up = false; + break; + } + + hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */ + + putstr("\neth link changed: speed = "); + puthex16_nl(speed); +} + +void +timer_irq_handler(unsigned irq) +{ + hal_set_timeout(timer_delta); // schedule next timeout + send_packet_now = 1; +} + + +void +buffer_irq_handler(unsigned irq) +{ + // FIXME +} + +static void +init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum) +{ + int i = 0; + int mark = ((bufnum & 0xff) << 24) | 0x005A0000; + + for (i = 0; i < BP_NLINES; i++){ + buf[i] = mark | i; + mark ^= 0x00FF0000; + } + + // copy header into buffer + memcpy_wa(buf, pkt, sizeof(*pkt)); +} + +static void +init_packets(void) +{ + int i; + + u2_eth_packet_t pkt __attribute__((aligned (4))); + + for (i = 0; i < 6; i++){ + pkt.ehdr.dst.addr[i] = dst_mac_addr[i]; + } + pkt.ehdr.src = *ethernet_mac_addr(); + pkt.ehdr.ethertype = U2_ETHERTYPE; + + // fill ALL buffers for debugging + for (i = 0; i < 8; i++) + init_packet((void *)buffer_ram(i), &pkt, i); +} + +static int led_counter = 0; + +int +main(void) +{ + int send_pause = 1; + + u2_init(); + + // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output + //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + + putstr("\ngen_eth_packets\n"); + + // Control LEDs + output_regs->leds = 0x00; + + init_packets(); + + // pic_register_handler(IRQ_BUFFER, buffer_irq_handler); // poll for now + pic_register_handler(IRQ_TIMER, timer_irq_handler); + hal_set_timeout(timer_delta); + + ethernet_register_link_changed_callback(link_changed_callback); + + ethernet_init(); + + eth_mac->pause_frame_send_en = 1; + eth_mac->pause_quanta_set = 16384 / 512; + + // eth_mac->speed = 4; // FIXME hardcode mac speed to 1000 + + while(1){ + if (link_is_up && send_packet_now){ + send_packet_now = false; + + + if (send_pause) + eth_mac->xon_cpu = 1; + else + eth_mac->xon_cpu = 0; + + send_pause ^= 1; + + // kick off the next packet + // FIXME set packet number in packet + +#if 0 + bp_send_from_buf(0, PORT_ETH, 1, 0, 255); // 1KB total + + while ((buffer_pool_status->status & (BPS_DONE_0|BPS_ERROR_0)) == 0) + ; + bp_clear_buf(0); +#endif + + output_regs->leds = ((++led_counter) & 0x1) | (link_is_up ? 0x2 : 0x0); + } + } + + hal_finish(); + return 1; +} diff --git a/firmware/microblaze/apps/cruft/hello.c b/firmware/microblaze/apps/cruft/hello.c new file mode 100644 index 000000000..bce843093 --- /dev/null +++ b/firmware/microblaze/apps/cruft/hello.c @@ -0,0 +1,30 @@ +/* + * Copyright 2007 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, see . + */ + +#include "u2_init.h" +#include "stdio.h" + +int +main(void) +{ + u2_init(); + + puts("Hello World"); + puts("Goodbye World"); + + return 0; +} diff --git a/firmware/microblaze/apps/cruft/ibs_rx_test.c b/firmware/microblaze/apps/cruft/ibs_rx_test.c new file mode 100644 index 000000000..bdc04747e --- /dev/null +++ b/firmware/microblaze/apps/cruft/ibs_rx_test.c @@ -0,0 +1,82 @@ +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "nonstdio.h" + +#define PORT 2 // ethernet = 2, serdes = 0 +int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf; +int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle; + +int buffer_state[4]; + +static void __attribute__((unused)) +wait_until_status_nonzero(void) +{ + while (buffer_pool_status->status == 0) + ; +} + +int +main(void) +{ + int i; + + u2_init(); + + output_regs->adc_ctrl = 0x0A; + + dsp_rx_regs->freq = 0; + dsp_rx_regs->scale_iq = (1 << 16) | 1; + dsp_rx_regs->decim_rate = 8; + + volatile unsigned int *buffer0 = buffer_ram(0); + volatile unsigned int *buffer1 = buffer_ram(1); + volatile unsigned int *buffer2 = buffer_ram(2); + + putstr("Starting RX\n"); + bp_clear_buf(0); + bp_receive_to_buf(0, 1, 1, 0, 99); + + dsp_rx_regs->rx_command = (50 << 9) | 100; // Numlines, lines per frame + dsp_rx_regs->rx_time = 0x2000; + + dsp_rx_regs->rx_command = (137 << 9) | 50; // Numlines, lines per frame + dsp_rx_regs->rx_time = 0x2200; + + while (buffer_pool_status->status == 0) + ; + bp_clear_buf(0); + bp_clear_buf(1); + bp_receive_to_buf(1, 1, 1, 0, 99); + while (buffer_pool_status->status == 0) + ; + bp_clear_buf(2); + bp_receive_to_buf(2, 1, 1, 0, 99); + while (buffer_pool_status->status == 0) + ; + + for(i=0;i<100;i++) { + puthex(i); + putstr(" "); + puthex_nl(buffer0[i]); + } + for(i=0;i<60;i++) { + puthex(i); + putstr(" "); + puthex_nl(buffer1[i]); + } + for(i=0;i<60;i++) { + puthex(i); + putstr(" "); + puthex_nl(buffer2[i]); + } + //while(timer_regs -> time < 0x6000) + // {} + + putstr("Done\n"); + hal_finish(); + + return 1; +} diff --git a/firmware/microblaze/apps/cruft/ibs_tx_test.c b/firmware/microblaze/apps/cruft/ibs_tx_test.c new file mode 100644 index 000000000..ff9446d92 --- /dev/null +++ b/firmware/microblaze/apps/cruft/ibs_tx_test.c @@ -0,0 +1,160 @@ +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "nonstdio.h" + +// Globals +#define EMPTY 0 +#define FILLING 1 +#define FULL 2 +#define EMPTYING 3 + +#define PORT 2 // ethernet = 2, serdes = 0 +int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf; +int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle; + +int buffer_state[4]; + +static void +wait_until_status_nonzero(void) +{ + while (buffer_pool_status->status == 0) + ; +} + +int +main(void) +{ + int i; + + u2_init(); + + dsp_tx_regs->freq = 0; + dsp_tx_regs->scale_iq = (1 << 16) | 1; + dsp_tx_regs->interp_rate = 8; + + // Write data to be sent into the first buffer + volatile unsigned int *buffer0 = buffer_ram(0); + volatile unsigned int *buffer1 = buffer_ram(1); + + + putstr("Starting to fill in RAM\n"); + for(i=0;i<512;i++) + buffer0[i] = i; + putstr("Filled in RAM\n"); + + buffer0[0] = 7; // start and end of buffer, send immediately + buffer0[1] = 0x0000; // start time + bp_clear_buf(0); + bp_send_from_buf(0, 1, 1, 0, 9); + while (buffer_pool_status->status == 0) + ; + while(timer_regs -> time < 0x6000) + {} + + buffer0[0] = 3; // start and end of buffer + buffer0[1] = 0x8000; // start time + bp_clear_buf(0); + bp_send_from_buf(0, 1, 1, 0, 9); + while (buffer_pool_status->status == 0) + ; + while(timer_regs -> time < 0x8400) + {} + + buffer0[0] = 3; // start and end of buffer + buffer0[1] = 0x8800; // start time + bp_clear_buf(0); + bp_send_from_buf(0, 1, 1, 0, 9); + while (buffer_pool_status->status == 0) + ; + while(timer_regs -> time < 0x9000) + {} + + buffer0[0] = 0x2; // not last + buffer0[1] = 0x9100; // start time + bp_clear_buf(0); + bp_send_from_buf(0, 1, 1, 0, 9); + while (buffer_pool_status->status == 0) + ; + buffer0[0] = 0x1; // last + buffer0[1] = 0x0000; // start time + bp_clear_buf(0); + bp_send_from_buf(0, 1, 1, 0, 9); + while (buffer_pool_status->status == 0) + ; + + + buffer0[0] = 0x3; // first and last + buffer0[1] = 0x8000; // Time in the past + bp_clear_buf(0); + bp_send_from_buf(0, 1, 1, 0, 9); + while (buffer_pool_status->status == 0) + ; + + /* + buffer0[0] = 0x2; // not last + buffer0[1] = 0x9600; // start time + bp_clear_buf(0); + bp_send_from_buf(0, 1, 1, 0, 9); + while (buffer_pool_status->status == 0) + ; + */ + + while(timer_regs -> time < 0xa000) + {} + + putstr("Done\n"); + + while(1) + {} + hal_finish(); + + // Send a bunch, let them pile up in FIFO + bp_send_from_buf(0, 2, 1, 21, 80); wait_until_status_nonzero(); + bp_clear_buf(0); + putstr("First add'l TX done\n"); + bp_send_from_buf(0, 2, 1, 81, 288); wait_until_status_nonzero(); + bp_clear_buf(0); + bp_send_from_buf(0, 2, 1, 289, 292); wait_until_status_nonzero(); + bp_clear_buf(0); + bp_send_from_buf(0, 2, 1, 293, 326); wait_until_status_nonzero(); + bp_clear_buf(0); + bp_send_from_buf(0, 2, 1, 327, 399); wait_until_status_nonzero(); + bp_clear_buf(0); + bp_send_from_buf(0, 2, 1, 400, 511); wait_until_status_nonzero(); + bp_clear_buf(0); + putstr("All add'l TX done\n"); + + bp_receive_to_buf(1, 2, 1, 21, 80); wait_until_status_nonzero(); + bp_clear_buf(1); + putstr("First add'l RX done\n"); + bp_receive_to_buf(1, 2, 1, 81, 288); wait_until_status_nonzero(); + bp_clear_buf(1); + bp_receive_to_buf(1, 2, 1, 289, 292); wait_until_status_nonzero(); + bp_clear_buf(1); + bp_receive_to_buf(1, 2, 1, 293, 326); wait_until_status_nonzero(); + bp_clear_buf(1); + bp_receive_to_buf(1, 2, 1, 327, 399); wait_until_status_nonzero(); + bp_clear_buf(1); + bp_receive_to_buf(1, 2, 1, 400, 511); wait_until_status_nonzero(); + bp_clear_buf(1); + putstr("All add'l RX done\n"); + + for(i=0;i<512;i++) + if(buffer0[i] != buffer1[i]) { + putstr("ERROR at location: "); + puthex_nl(i); + putstr("Value sent: "); + puthex_nl(buffer0[i]); + putstr("Value rcvd: "); + puthex_nl(buffer1[i]); + //break; + } + + putstr("Done Testing\n"); + + hal_finish(); + return 1; +} diff --git a/firmware/microblaze/apps/cruft/mimo_app_common_v2.c b/firmware/microblaze/apps/cruft/mimo_app_common_v2.c new file mode 100644 index 000000000..5dbecb0d0 --- /dev/null +++ b/firmware/microblaze/apps/cruft/mimo_app_common_v2.c @@ -0,0 +1,582 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mimo_app_common_v2.h" +#include "buffer_pool.h" +#include "memcpy_wa.h" +#include "ethernet.h" +#include "nonstdio.h" +#include "print_rmon_regs.h" +#include "db.h" +#include "db_base.h" +#include "clocks.h" +#include "u2_init.h" +#include + +volatile bool link_is_up = false; // eth handler sets this +int cpu_tx_buf_dest_port = PORT_ETH; + +// If this is non-zero, this dbsm could be writing to the ethernet +dbsm_t *ac_could_be_sending_to_eth; + +static unsigned char exp_seqno __attribute__((unused)) = 0; + +void abort(void); + +static bool +burn_mac_addr(const op_burn_mac_addr_t *p) +{ + return ethernet_set_mac_addr(&p->addr); +} + +static bool +sync_to_pps(const op_generic_t *p) +{ + timesync_regs->sync_on_next_pps = 1; + putstr("SYNC to PPS\n"); + return true; +} + +static bool +config_mimo_cmd(const op_config_mimo_t *p) +{ + clocks_mimo_config(p->flags); + return true; +} + +void +set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt) +{ + reply_pkt->ehdr.dst = cmd_pkt->ehdr.src; + reply_pkt->ehdr.src = *ethernet_mac_addr(); + reply_pkt->ehdr.ethertype = U2_ETHERTYPE; + reply_pkt->thdr.flags = 0; + reply_pkt->thdr.fifo_status = 0; // written by protocol engine + reply_pkt->thdr.seqno = 0; // written by protocol engine + reply_pkt->thdr.ack = 0; // written by protocol engine + u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN); + reply_pkt->fixed.timestamp = timer_regs->time; +} + +static void +send_reply(unsigned char *reply, size_t reply_len) +{ + if (reply_len < 64) + reply_len = 64; + + // wait for buffer to become idle + hal_set_leds(0x4, 0x4); + while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0) + ; + hal_set_leds(0x0, 0x4); + + // copy reply into CPU_TX_BUF + memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len); + + // wait until nobody else is sending to the ethernet + if (ac_could_be_sending_to_eth){ + hal_set_leds(0x8, 0x8); + dbsm_wait_for_opening(ac_could_be_sending_to_eth); + hal_set_leds(0x0, 0x8); + } + + if (0){ + printf("sending_reply to port %d, len = %d\n", cpu_tx_buf_dest_port, (int)reply_len); + print_buffer(buffer_ram(CPU_TX_BUF), reply_len/4); + } + + // fire it off + bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 1, 0, reply_len/4); + + // wait for it to complete (not long, it's a small pkt) + while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0) + ; + + bp_clear_buf(CPU_TX_BUF); +} + + +static size_t +op_id_cmd(const op_generic_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_id_reply_t *r = (op_id_reply_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) // no room + return 0; + + // Build reply subpacket + + r->opcode = OP_ID_REPLY; + r->len = sizeof(op_id_reply_t); + r->rid = p->rid; + r->addr = *ethernet_mac_addr(); + r->hw_rev = (u2_hw_rev_major << 8) | u2_hw_rev_minor; + // r->fpga_md5sum = ; // FIXME + // r->sw_md5sum = ; // FIXME + + return r->len; +} + + +static size_t +config_tx_v2_cmd(const op_config_tx_v2_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_config_tx_reply_v2_t *r = (op_config_tx_reply_v2_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) + return 0; // no room + + struct tune_result tune_result; + memset(&tune_result, 0, sizeof(tune_result)); + + bool ok = true; + +#if 0 + if (p->valid & CFGV_GAIN){ + ok &= db_set_gain(tx_dboard, p->gain); + } + + if (p->valid & CFGV_FREQ){ + bool was_streaming = is_streaming(); + if (was_streaming) + stop_rx_cmd(); + + u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo); + bool tune_ok = db_tune(tx_dboard, f, &tune_result); + ok &= tune_ok; + print_tune_result("Tx", tune_ok, f, &tune_result); + + if (was_streaming) + restart_streaming(); + } + + if (p->valid & CFGV_INTERP_DECIM){ + int interp = p->interp; + int hb1 = 0; + int hb2 = 0; + + if (!(interp & 1)){ + hb2 = 1; + interp = interp >> 1; + } + + if (!(interp & 1)){ + hb1 = 1; + interp = interp >> 1; + } + + if (interp < MIN_CIC_INTERP || interp > MAX_CIC_INTERP) + ok = false; + else { + dsp_tx_regs->interp_rate = (hb1<<9) | (hb2<<8) | interp; + // printf("Interp: %d, register %d\n", p->interp, (hb1<<9) | (hb2<<8) | interp); + } + } + + if (p->valid & CFGV_SCALE_IQ){ + dsp_tx_regs->scale_iq = p->scale_iq; + } +#endif + + // Build reply subpacket + + r->opcode = OP_CONFIG_TX_REPLY_V2; + r->len = sizeof(*r); + r->rid = p->rid; + r->ok = ok; + r->inverted = tune_result.inverted; + r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq); + r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq); + r->duc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq); + r->duc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq); + r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq); + r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq); + return r->len; +} + +static size_t +config_rx_v2_cmd(const op_config_rx_v2_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_config_rx_reply_v2_t *r = (op_config_rx_reply_v2_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) + return 0; // no room + + struct tune_result tune_result; + memset(&tune_result, 0, sizeof(tune_result)); + + bool ok = true; + + if (p->valid & CFGV_GAIN){ + ok &= db_set_gain(rx_dboard, p->gain); + } + + if (p->valid & CFGV_FREQ){ + bool was_streaming = is_streaming(); + if (was_streaming) + stop_rx_cmd(); + + u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo); + bool tune_ok = db_tune(rx_dboard, f, &tune_result); + ok &= tune_ok; + print_tune_result("Rx", tune_ok, f, &tune_result); + + if (was_streaming) + restart_streaming(); + } + + if (p->valid & CFGV_INTERP_DECIM){ + int decim = p->decim; + int hb1 = 0; + int hb2 = 0; + + if(!(decim & 1)) { + hb2 = 1; + decim = decim >> 1; + } + + if(!(decim & 1)) { + hb1 = 1; + decim = decim >> 1; + } + + if (decim < MIN_CIC_DECIM || decim > MAX_CIC_DECIM) + ok = false; + else { + dsp_rx_regs->decim_rate = (hb1<<9) | (hb2<<8) | decim; + // printf("Decim: %d, register %d\n", p->decim, (hb1<<9) | (hb2<<8) | decim); + } + } + + if (p->valid & CFGV_SCALE_IQ){ + dsp_rx_regs->scale_iq = p->scale_iq; + } + + // Build reply subpacket + + r->opcode = OP_CONFIG_RX_REPLY_V2; + r->len = sizeof(*r); + r->rid = p->rid; + r->ok = ok; + r->inverted = tune_result.inverted; + r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq); + r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq); + r->ddc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq); + r->ddc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq); + r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq); + r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq); + + return r->len; +} + +static size_t +read_time_cmd(const op_generic_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_read_time_reply_t *r = (op_read_time_reply_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) + return 0; // no room + + r->opcode = OP_READ_TIME_REPLY; + r->len = sizeof(*r); + r->rid = p->rid; + r->time = timer_regs->time; + + return r->len; +} + +static void +fill_db_info(u2_db_info_t *p, const struct db_base *db) +{ + p->dbid = db->dbid; + p->freq_min_hi = u2_fxpt_freq_hi(db->freq_min); + p->freq_min_lo = u2_fxpt_freq_lo(db->freq_min); + p->freq_max_hi = u2_fxpt_freq_hi(db->freq_max); + p->freq_max_lo = u2_fxpt_freq_lo(db->freq_max); + p->gain_min = db->gain_min; + p->gain_max = db->gain_max; + p->gain_step_size = db->gain_step_size; +} + +static size_t +dboard_info_cmd(const op_generic_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_dboard_info_reply_t *r = (op_dboard_info_reply_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) + return 0; // no room + + r->opcode = OP_DBOARD_INFO_REPLY; + r->len = sizeof(*r); + r->rid = p->rid; + r->ok = true; + + fill_db_info(&r->tx_db_info, tx_dboard); + fill_db_info(&r->rx_db_info, rx_dboard); + + return r->len; +} + +static size_t +peek_cmd(const op_peek_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_generic_t *r = (op_generic_t *) reply_payload; + + putstr("peek: addr="); puthex32(p->addr); + printf(" bytes=%u\n", p->bytes); + + if ((reply_payload_space < (sizeof(*r) + p->bytes)) || + p->bytes > MAX_SUBPKT_LEN - sizeof(op_generic_t)) { + putstr("peek: insufficient reply packet space\n"); + return 0; // FIXME do partial read? + } + + r->opcode = OP_PEEK_REPLY; + r->len = sizeof(*r)+p->bytes; + r->rid = p->rid; + r->ok = true; + + memcpy_wa(reply_payload+sizeof(*r), (void *)p->addr, p->bytes); + + return r->len; +} + +static bool +poke_cmd(const op_poke_t *p) +{ + int bytes = p->len - sizeof(*p); + putstr("poke: addr="); puthex32(p->addr); + printf(" bytes=%u\n", bytes); + + uint8_t *src = (uint8_t *)p + sizeof(*p); + memcpy_wa((void *)p->addr, src, bytes); + + return true; +} + +static size_t +generic_reply(const op_generic_t *p, + void *reply_payload, size_t reply_payload_space, + bool ok) +{ + op_generic_t *r = (op_generic_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) + return 0; // no room + + r->opcode = p->opcode | OP_REPLY_BIT; + r->len = sizeof(*r); + r->rid = p->rid; + r->ok = ok; + + return r->len; +} + +static size_t +add_eop(void *reply_payload, size_t reply_payload_space) +{ + op_generic_t *r = (op_generic_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) + return 0; // no room + + r->opcode = OP_EOP; + r->len = sizeof(*r); + r->rid = 0; + r->ok = 0; + + return r->len; +} + +void +handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len) +{ + unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4; + unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)]; + int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t); + + // initialize reply + memset(reply, 0, sizeof(reply)); + set_reply_hdr((u2_eth_packet_t *) reply, pkt); + + // point to beginning of payload (subpackets) + unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t); + int payload_len = len - sizeof(u2_eth_packet_t); + + size_t subpktlen = 0; + + while (payload_len >= sizeof(op_generic_t)){ + const op_generic_t *gp = (const op_generic_t *) payload; + subpktlen = 0; + + // printf("\nopcode = %d\n", gp->opcode); + + switch(gp->opcode){ + case OP_EOP: // end of subpackets + goto end_of_subpackets; + + case OP_ID: + subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space); + break; + + case OP_CONFIG_TX_V2: + subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload, + reply_payload, reply_payload_space); + break; + + case OP_CONFIG_RX_V2: + subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload, + reply_payload, reply_payload_space); + break; + + case OP_START_RX_STREAMING: + start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload); + subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true); + break; + + case OP_STOP_RX: + stop_rx_cmd(); + subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true); + break; + + case OP_BURN_MAC_ADDR: + subpktlen = generic_reply(gp, reply_payload, reply_payload_space, + burn_mac_addr((op_burn_mac_addr_t *) payload)); + break; + + case OP_CONFIG_MIMO: + subpktlen = generic_reply(gp, reply_payload, reply_payload_space, + config_mimo_cmd((op_config_mimo_t *) payload)); + break; + + case OP_READ_TIME: + subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space); + break; + + case OP_DBOARD_INFO: + subpktlen = dboard_info_cmd(gp, reply_payload, reply_payload_space); + break; + + case OP_SYNC_TO_PPS: + subpktlen = generic_reply(gp, reply_payload, reply_payload_space, + sync_to_pps((op_generic_t *) payload)); + break; + + case OP_PEEK: + subpktlen = peek_cmd((op_peek_t *)payload, reply_payload, reply_payload_space); + break; + + case OP_POKE: + subpktlen = generic_reply(gp, reply_payload, reply_payload_space, + poke_cmd((op_poke_t *)payload)); + break; + + default: + printf("app_common_v2: unhandled opcode = %d\n", gp->opcode); + break; + } + + int t = (gp->len + 3) & ~3; // bump to a multiple of 4 + payload += t; + payload_len -= t; + + subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4 + reply_payload += subpktlen; + reply_payload_space -= subpktlen; + } + + end_of_subpackets: + + // add the EOP marker + subpktlen = add_eop(reply_payload, reply_payload_space); + subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4 + reply_payload += subpktlen; + reply_payload_space -= subpktlen; + + send_reply(reply, reply_payload - reply); +} + + +/* + * Called when an ethernet packet is received. + * Return true if we handled it here, otherwise + * it'll be passed on to the DSP Tx pipe + */ +int +eth_pkt_inspector(bsm12_t *sm, int bufno) +{ + u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno); + size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4; + + //static size_t last_len = 0; + + // hal_toggle_leds(0x1); + + // inspect rcvd frame and figure out what do do. + + if (pkt->ehdr.ethertype != U2_ETHERTYPE) + return true; // ignore, probably bogus PAUSE frame from MAC + + int chan = u2p_chan(&pkt->fixed); + + switch (chan){ + case CONTROL_CHAN: + handle_control_chan_frame(pkt, byte_len); + return -1; + break; + + case 0: + return 0; // pass it off to DSP TX + + case 1: + return 1; // pass it off to SERDES TX + + default: + abort(); + break; + } +} + +/* + * Called when eth phy state changes (w/ interrupts disabled) + */ +void +link_changed_callback(int speed) +{ + link_is_up = speed != 0; + hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45); + printf("\neth link changed: speed = %d\n", speed); +} + + +void +print_tune_result(char *msg, bool tune_ok, + u2_fxpt_freq_t target_freq, struct tune_result *r) +{ +#if 0 + printf("db_tune %s %s\n", msg, tune_ok ? "true" : "false"); + putstr(" target_freq "); print_fxpt_freq(target_freq); newline(); + putstr(" baseband_freq "); print_fxpt_freq(r->baseband_freq); newline(); + putstr(" dxc_freq "); print_fxpt_freq(r->dxc_freq); newline(); + putstr(" residual_freq "); print_fxpt_freq(r->residual_freq); newline(); + printf(" inverted %s\n", r->inverted ? "true" : "false"); +#endif +} diff --git a/firmware/microblaze/apps/cruft/mimo_app_common_v2.h b/firmware/microblaze/apps/cruft/mimo_app_common_v2.h new file mode 100644 index 000000000..1e62ced37 --- /dev/null +++ b/firmware/microblaze/apps/cruft/mimo_app_common_v2.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008 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, see . + */ + +#ifndef INCLUDED_APP_COMMON_H +#define INCLUDED_APP_COMMON_H + +#include +#include "usrp2_eth_packet.h" +#include "bsm12.h" +#include "memory_map.h" +#include "hal_io.h" +#include +#include + +#define CPU_TX_BUF 7 // cpu -> eth + +#define _AL4 __attribute__((aligned (4))) + +extern volatile bool link_is_up; // eth handler sets this + +// If there's a dbsm that sends to the ethernet, put it's address here +extern dbsm_t *ac_could_be_sending_to_eth; + +extern int cpu_tx_buf_dest_port; + +void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt); + +/* + * Called when an ethernet packet is received. + */ +int eth_pkt_inspector(bsm12_t *sm, int bufno); + + +void link_changed_callback(int speed); + +void +print_tune_result(char *msg, bool tune_ok, + u2_fxpt_freq_t target_freq, struct tune_result *r); + + +void start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p); +void stop_rx_cmd(void); +void restart_streaming(void); +bool is_streaming(void); + +void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len); + +#endif /* INCLUDED_APP_COMMON_H */ diff --git a/firmware/microblaze/apps/cruft/mimo_tx.c b/firmware/microblaze/apps/cruft/mimo_tx.c new file mode 100644 index 000000000..e0f8aa6fa --- /dev/null +++ b/firmware/microblaze/apps/cruft/mimo_tx.c @@ -0,0 +1,363 @@ +/* + * Copyright 2007,2008,2009 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, see . + */ + +/* + * This is a down and dirty test program that confirms that the we can + * coherently transmit different signals to two USRP2s connected via a + * mimo cable. This code runs in the USRP2 connected to the ethernet. + * The other USRP runs mimo_tx_slave. The host runs test_mimo_tx. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "bsm12.h" +#include "mimo_app_common_v2.h" +#include "memcpy_wa.h" +#include +#include +#include +#include "clocks.h" + +#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) + +#if (FW_SETS_SEQNO) +static int fw_seqno; // used when f/w is filling in sequence numbers +#endif + + +/* + * Experimental code to transmit packets to DSP Tx and SERDES + * + * Hard wire the Tx config so we don't have to deal with control stuff yet. + */ + +#define BUF_BSM12_0 4 +#define BUF_BSM12_1 5 +#define BUF_BSM12_2 6 + +//#define CPU_TX_BUF 7 // cpu -> eth + +// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) +// DSP Tx reads word0 (flags) + timestamp followed by samples + +#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) + +// Receive from ethernet +buf_cmd_args_t bsm12_recv_args = { + PORT_ETH, + 0, + BP_LAST_LINE +}; + +// send to DSP Tx +buf_cmd_args_t bsm12_send0_args = { + PORT_DSP, + DSP_TX_FIRST_LINE, // starts just past transport header + 0 // filled in from last_line register +}; + +// send to SERDES +buf_cmd_args_t bsm12_send1_args = { + PORT_SERDES, + 0, // starts just past transport header + 0 // filled in from last_line register +}; + +bsm12_t bsm12_sm; // the state machine + +#if 0 +/* + * ================================================================ + * configure DSP RX double buffering state machine (dsp -> eth) + * ================================================================ + */ + +// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0) +// DSP Rx writes timestamp followed by nlines_per_frame of samples +#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1) + +// receive from DSP +buf_cmd_args_t dsp_rx_recv_args = { + PORT_DSP, + DSP_RX_FIRST_LINE, + BP_LAST_LINE +}; + +// send to ETH +buf_cmd_args_t dsp_rx_send_args = { + PORT_ETH, + 0, // starts with ethernet header in line 0 + 0, // filled in from list_line register +}; + +dbsm_t dsp_rx_sm; // the state machine +#endif + + +// The mac address of the host we're sending to. +eth_mac_addr_t host_mac_addr; + + +// variables for streaming mode + +static bool streaming_p = false; +static unsigned int streaming_items_per_frame = 0; +static int streaming_frame_count = 0; +#define FRAMES_PER_CMD 1000 + +bool is_streaming(void){ return streaming_p; } + + +// ---------------------------------------------------------------- + + +void +restart_streaming(void) +{ +#if 0 + // setup RX DSP regs + dsp_rx_regs->clear_state = 1; // reset + + streaming_p = true; + streaming_frame_count = FRAMES_PER_CMD; + + dsp_rx_regs->rx_command = + MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, + streaming_items_per_frame, + 1, 1); // set "chain" bit + + // kick off the state machine + dbsm_start(&dsp_rx_sm); + + dsp_rx_regs->rx_time = 0; // enqueue first of two commands + + // make sure this one and the rest have the "now" and "chain" bits set. + dsp_rx_regs->rx_command = + MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, + streaming_items_per_frame, + 1, 1); + + dsp_rx_regs->rx_time = 0; // enqueue second command +#endif +} + +void +start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p) +{ +#if 0 + host_mac_addr = *host; // remember who we're sending to + + /* + * Construct ethernet header and word0 and preload into two buffers + */ + u2_eth_packet_t pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.ehdr.dst = *host; + pkt.ehdr.src = *ethernet_mac_addr(); + pkt.ehdr.ethertype = U2_ETHERTYPE; + u2p_set_word0(&pkt.fixed, 0, 0); + // DSP RX will fill in timestamp + + memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt)); + memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt)); + + + if (FW_SETS_SEQNO) + fw_seqno = 0; + + streaming_items_per_frame = p->items_per_frame; + restart_streaming(); +#endif +} + + +void +stop_rx_cmd(void) +{ +#if 0 + streaming_p = false; + dsp_rx_regs->clear_state = 1; // flush cmd queue + bp_clear_buf(DSP_RX_BUF_0); + bp_clear_buf(DSP_RX_BUF_1); +#endif +} + + +static void +setup_tx() +{ + dsp_tx_regs->clear_state = 1; + + int tx_scale = 2500; + int interp = 8; // * 4 + + // setup some defaults + + dsp_tx_regs->freq = 429496730; // 10MHz + dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; + dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp; +} + + +#if 0 +#if (FW_SETS_SEQNO) +/* + * Debugging ONLY. This will be handled by the tx_protocol_engine. + * + * This is called when the DSP Rx chain has filled in a packet. + * We set and increment the seqno, then return false, indicating + * that we didn't handle the packet. A bit of a kludge + * but it should work. + */ +int +fw_sets_seqno_inspector(bsm12_t *sm, int buf_this) +{ + uint32_t *p = buffer_ram(buf_this); + uint32_t seqno = fw_seqno++; + + // KLUDGE all kinds of nasty magic numbers and embedded knowledge + uint32_t t = p[4]; + t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); + p[4] = t; + + // queue up another rx command when required + if (streaming_p && --streaming_frame_count == 0){ + streaming_frame_count = FRAMES_PER_CMD; + dsp_rx_regs->rx_time = 0; + } + + return false; // we didn't handle the packet +} +#endif +#endif + + +inline static void +buffer_irq_handler(unsigned irq) +{ + uint32_t status = buffer_pool_status->status; + + bsm12_process_status(&bsm12_sm, status); +} + +int +main(void) +{ + u2_init(); + + putstr("\nMIMO Tx\n"); + print_mac_addr(ethernet_mac_addr()->addr); + newline(); + + ethernet_register_link_changed_callback(link_changed_callback); + ethernet_init(); + + clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO); + +#if 0 + // make bit 15 of Tx gpio's be a s/w output + hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); + hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); +#endif + + output_regs->debug_mux_ctrl = 1; +#if 0 + hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); + hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); +#endif + + + // initialize double buffering state machine for ethernet -> DSP Tx + + bsm12_init(&bsm12_sm, BUF_BSM12_0, + &bsm12_recv_args, &bsm12_send0_args, &bsm12_send1_args, + eth_pkt_inspector); + + +#if 0 + // initialize double buffering state machine for DSP RX -> Ethernet + + if (FW_SETS_SEQNO){ + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + fw_sets_seqno_inspector); + } + else { + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + dbsm_nop_inspector); + } + + // tell app_common that this dbsm could be sending to the ethernet + ac_could_be_sending_to_eth = &dsp_rx_sm; +#endif + + + // program tx registers + setup_tx(); + + // kick off the state machine + bsm12_start(&bsm12_sm); + + //int which = 0; + + while(1){ + // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); + // which ^= 0x8000; + + buffer_irq_handler(0); + + int pending = pic_regs->pending; // poll for under or overrun + + if (pending & PIC_UNDERRUN_INT){ + // dbsm_handle_tx_underrun(&dsp_tx_sm); + pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt + putchar('U'); + } + + if (pending & PIC_OVERRUN_INT){ + // dbsm_handle_rx_overrun(&dsp_rx_sm); + pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt + + // FIXME Figure out how to handle this robustly. + // Any buffers that are emptying should be allowed to drain... + + if (streaming_p){ + // restart_streaming(); + // FIXME report error + } + else { + // FIXME report error + } + putchar('O'); + } + } +} diff --git a/firmware/microblaze/apps/cruft/mimo_tx_slave.c b/firmware/microblaze/apps/cruft/mimo_tx_slave.c new file mode 100644 index 000000000..cdf9c03c2 --- /dev/null +++ b/firmware/microblaze/apps/cruft/mimo_tx_slave.c @@ -0,0 +1,376 @@ +/* + * Copyright 2007,2008,2009 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, see . + */ + +/* + * This is a down and dirty test program that confirms that the we can + * coherently transmit different signals to two USRP2s connected via a + * mimo cable. This code runs in the USRP2 NOT connected to the + * ethernet. The USRP connected to the ethernet runs mimo_tx. The + * host runs test_mimo_tx. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "dbsm.h" +#include "app_common_v2.h" +#include "memcpy_wa.h" +#include "clocks.h" +#include +#include +#include + + +#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) + +#if (FW_SETS_SEQNO) +static int fw_seqno; // used when f/w is filling in sequence numbers +#endif + + +/* + * Full duplex Tx and Rx between serdes and DSP pipelines + * + * Buffer 1 is used by the cpu to send frames to the host. + * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow + * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow + */ +//#define CPU_RX_BUF 0 // eth -> cpu + +#define DSP_RX_BUF_0 2 // dsp rx -> serdes (double buffer) +#define DSP_RX_BUF_1 3 // dsp rx -> serdes +#define DSP_TX_BUF_0 4 // serdes -> dsp tx (double buffer) +#define DSP_TX_BUF_1 5 // serdes -> dsp tx + +/* + * ================================================================== + * configure DSP TX double buffering state machine (serdes -> dsp) + * ================================================================== + */ + +// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) +// DSP Tx reads word0 (flags) + timestamp followed by samples + +#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) + +// Receive from serdes +buf_cmd_args_t dsp_tx_recv_args = { + PORT_SERDES, + 0, + BP_LAST_LINE +}; + +// send to DSP Tx +buf_cmd_args_t dsp_tx_send_args = { + PORT_DSP, + DSP_TX_FIRST_LINE, // starts just past transport header + 0 // filled in from last_line register +}; + +dbsm_t dsp_tx_sm; // the state machine + +/* + * ================================================================= + * configure DSP RX double buffering state machine (dsp -> serdes) + * ================================================================= + */ + +// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0) +// DSP Rx writes timestamp followed by nlines_per_frame of samples +#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1) + +// receive from DSP +buf_cmd_args_t dsp_rx_recv_args = { + PORT_DSP, + DSP_RX_FIRST_LINE, + BP_LAST_LINE +}; + +// send to serdes +buf_cmd_args_t dsp_rx_send_args = { + PORT_SERDES, + 0, // starts with ethernet header in line 0 + 0, // filled in from list_line register +}; + +dbsm_t dsp_rx_sm; // the state machine + + +// The mac address of the host we're sending to. +eth_mac_addr_t host_mac_addr; + + +// variables for streaming mode + +static bool streaming_p = false; +static unsigned int streaming_items_per_frame = 0; +static int streaming_frame_count = 0; +#define FRAMES_PER_CMD 1000 + +bool is_streaming(void){ return streaming_p; } + +// ---------------------------------------------------------------- + + +void +restart_streaming(void) +{ + // setup RX DSP regs + dsp_rx_regs->clear_state = 1; // reset + + streaming_p = true; + streaming_frame_count = FRAMES_PER_CMD; + + dsp_rx_regs->rx_command = + MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, + streaming_items_per_frame, + 1, 1); // set "chain" bit + + // kick off the state machine + dbsm_start(&dsp_rx_sm); + + dsp_rx_regs->rx_time = 0; // enqueue first of two commands + + // make sure this one and the rest have the "now" and "chain" bits set. + dsp_rx_regs->rx_command = + MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, + streaming_items_per_frame, + 1, 1); + + dsp_rx_regs->rx_time = 0; // enqueue second command +} + +void +start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p) +{ + host_mac_addr = *host; // remember who we're sending to + + /* + * Construct ethernet header and word0 and preload into two buffers + */ + u2_eth_packet_t pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.ehdr.dst = *host; + pkt.ehdr.src = *ethernet_mac_addr(); + pkt.ehdr.ethertype = U2_ETHERTYPE; + u2p_set_word0(&pkt.fixed, 0, 0); + // DSP RX will fill in timestamp + + memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt)); + memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt)); + + + if (FW_SETS_SEQNO) + fw_seqno = 0; + + streaming_items_per_frame = p->items_per_frame; + restart_streaming(); +} + + +void +stop_rx_cmd(void) +{ + streaming_p = false; + dsp_rx_regs->clear_state = 1; // flush cmd queue + bp_clear_buf(DSP_RX_BUF_0); + bp_clear_buf(DSP_RX_BUF_1); +} + + +static void +setup_tx() +{ + dsp_tx_regs->clear_state = 1; + bp_clear_buf(DSP_TX_BUF_0); + bp_clear_buf(DSP_TX_BUF_1); + + int tx_scale = 2500; + int interp = 8; // * 4 + + // setup some defaults + + dsp_tx_regs->freq = 429496730; // 10MHz + dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; + dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp; +} + + +#if (FW_SETS_SEQNO) +/* + * Debugging ONLY. This will be handled by the tx_protocol_engine. + * + * This is called when the DSP Rx chain has filled in a packet. + * We set and increment the seqno, then return false, indicating + * that we didn't handle the packet. A bit of a kludge + * but it should work. + */ +bool +fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false +{ + uint32_t *p = buffer_ram(buf_this); + uint32_t seqno = fw_seqno++; + + // KLUDGE all kinds of nasty magic numbers and embedded knowledge + uint32_t t = p[4]; + t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); + p[4] = t; + + // queue up another rx command when required + if (streaming_p && --streaming_frame_count == 0){ + streaming_frame_count = FRAMES_PER_CMD; + dsp_rx_regs->rx_time = 0; + } + + return false; // we didn't handle the packet +} +#endif + + +inline static void +buffer_irq_handler(unsigned irq) +{ + // hal_toggle_leds(LED_A); + + uint32_t status = buffer_pool_status->status; + + if (0 && (status & ~BPS_IDLE_ALL)){ + putstr("status = "); + puthex32_nl(status); + } + + dbsm_process_status(&dsp_tx_sm, status); + dbsm_process_status(&dsp_rx_sm, status); +} + +int +main(void) +{ + u2_init(); + + output_regs->led_src = 0x3; // h/w controls bottom two bits + clocks_enable_test_clk(true, 1); + + putstr("\nMIMO Tx Slave\n"); + + cpu_tx_buf_dest_port = PORT_SERDES; + + // ethernet_register_link_changed_callback(link_changed_callback); + // ethernet_init(); + + clocks_mimo_config(MC_WE_LOCK_TO_MIMO); + + // puts("post clocks_mimo_config"); + +#if 0 + // make bit 15 of Tx gpio's be a s/w output + hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); + hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); +#endif + +#if 0 + output_regs->debug_mux_ctrl = 1; + hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000"); + hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000"); + hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); + hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); +#endif + + + // initialize double buffering state machine for ethernet -> DSP Tx + + dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, + &dsp_tx_recv_args, &dsp_tx_send_args, + eth_pkt_inspector); + + + //output_regs->flush_icache = 1; + + // initialize double buffering state machine for DSP RX -> Ethernet + + if (FW_SETS_SEQNO){ + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + fw_sets_seqno_inspector); + } + else { + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + dbsm_nop_inspector); + } + + // puts("post dbsm_init's"); + + // tell app_common that this dbsm could be sending to the ethernet + ac_could_be_sending_to_eth = &dsp_rx_sm; + + + // program tx registers + setup_tx(); + + // puts("post setup_tx"); + + // kick off the state machine + dbsm_start(&dsp_tx_sm); + + // puts("post dbsm_start"); + + //int which = 0; + + while(1){ + // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); + // which ^= 0x8000; + + buffer_irq_handler(0); + + int pending = pic_regs->pending; // poll for under or overrun + + if (pending & PIC_UNDERRUN_INT){ + dbsm_handle_tx_underrun(&dsp_tx_sm); + pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt + putchar('U'); + } + + if (pending & PIC_OVERRUN_INT){ + dbsm_handle_rx_overrun(&dsp_rx_sm); + pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt + + // FIXME Figure out how to handle this robustly. + // Any buffers that are emptying should be allowed to drain... + + if (streaming_p){ + // restart_streaming(); + // FIXME report error + } + else { + // FIXME report error + } + putchar('O'); + } + } +} diff --git a/firmware/microblaze/apps/cruft/rcv_eth_packets.c b/firmware/microblaze/apps/cruft/rcv_eth_packets.c new file mode 100644 index 000000000..03fc94354 --- /dev/null +++ b/firmware/microblaze/apps/cruft/rcv_eth_packets.c @@ -0,0 +1,233 @@ +/* + * Copyright 2007 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "memcpy_wa.h" +#include +#include + + +// ---------------------------------------------------------------- + +static eth_mac_addr_t dst_mac_addr = + {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}; + + +// ---------------------------------------------------------------- + +#define PACKET_SIZE 1500 // bytes +#define ETH_DATA_RATE 1000000 // 1MB/s +#define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s + +#define TIMER_RATE 100000000 // 100 MHz clock + +static int timer_delta = TIMER_RATE/ETH_PACKET_RATE; // ticks between interrupts + +static volatile bool send_packet_now = false; // timer handler sets this +static volatile bool link_is_up = false; // eth handler sets this + +int packet_number = 0; + +// ---------------------------------------------------------------- + +// debugging output on tx pins +#define LS_MASK 0xE0000 +#define LS_1000 0x80000 +#define LS_100 0x40000 +#define LS_10 0x20000 + + +/* + * Called when eth phy state changes (w/ interrupts disabled) + */ +void +link_changed_callback(int speed) +{ + int v = 0; + switch(speed){ + case 10: + v = LS_10; + link_is_up = true; + break; + + case 100: + v = LS_100; + link_is_up = true; + break; + + case 1000: + v = LS_100; + link_is_up = true; + break; + + default: + v = 0; + link_is_up = false; + break; + } + + //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */ + + putstr("\neth link changed: speed = "); + puthex16_nl(speed); +} + +void +timer_irq_handler(unsigned irq) +{ + hal_set_timeout(timer_delta); // schedule next timeout + send_packet_now = 1; +} + + +void +buffer_irq_handler(unsigned irq) +{ + // FIXME +} + +static void +init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum) +{ + int i = 0; + int mark = ((bufnum & 0xff) << 24) | 0x005A0000; + + for (i = 0; i < BP_NLINES; i++){ + buf[i] = mark | i; + mark ^= 0x00FF0000; + } + + // copy header into buffer + memcpy_wa(buf, pkt, sizeof(*pkt)); +} + +static void +init_packets(void) +{ + int i; + + u2_eth_packet_t pkt __attribute__((aligned (4))); + + pkt.ehdr.dst = dst_mac_addr; + pkt.ehdr.src = *ethernet_mac_addr(); + pkt.ehdr.ethertype = U2_ETHERTYPE; + + // fill ALL buffers for debugging + for (i = 0; i < 8; i++) + init_packet((void *)buffer_ram(i), &pkt, i); +} + +int +main(void) +{ + u2_init(); + + int prev_leds = -1; + int new_leds = 0x00; + output_regs->leds = 0x00; + + int peak_hold_count = 0; + + // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output + //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + + putstr("\nrcv_eth_packets\n"); + + init_packets(); + + // pic_register_handler(IRQ_BUFFER, buffer_irq_handler); // poll for now + + // FIXME turn off timer since I don't think MTS and MFS instructions are implemented + // pic_register_handler(IRQ_TIMER, timer_irq_handler); + // hal_set_timeout(timer_delta); + + ethernet_register_link_changed_callback(link_changed_callback); + + ethernet_init(); + + //eth_mac->speed = 4; // FIXME hardcode mac speed to 1000 + + // kick off a receive + bp_receive_to_buf(2, PORT_ETH, 1, 0, 511); + + while(1){ + // u2_eth_packet_t pkt; + + new_leds = 0; + if (link_is_up) + new_leds = 0x2; + + if ((buffer_pool_status->status & (BPS_DONE_2|BPS_ERROR_2)) != 0){ + // we've got a packet! + +#if 0 + // copy to stack buffer so we can byte address it + memcpy_wa(&pkt, (void *)buffer_ram(2), sizeof(pkt)); + + putstr("Rx: src: "); + print_mac_addr(pkt.ehdr.dst_addr); + putstr(" dst: "); + print_mac_addr(pkt.ehdr.src_addr); + putstr(" ethtype: "); + puthex16(pkt.ehdr.ethertype); + putstr(" len: "); + int len = (buffer_pool_status->last_line[2] + 1) * 4; + puthex16_nl(len); +#else + volatile int *bp = buffer_ram(2); + int i; + for (i = 0; i < 16; i++){ + puthex8(i); + putchar(':'); + puthex32_nl(bp[i]); + } +#endif + + // kick off next receive + bp_clear_buf(2); + bp_receive_to_buf(2, PORT_ETH, 1, 0, 511); + + peak_hold_count = 2048 * 10; + } + + if (peak_hold_count > 0){ + peak_hold_count--; + new_leds |= 0x1; + } + + if (new_leds != prev_leds){ + prev_leds = new_leds; + output_regs->leds = new_leds; + } + } + + hal_finish(); + return 1; +} diff --git a/firmware/microblaze/apps/cruft/read_dbids.c b/firmware/microblaze/apps/cruft/read_dbids.c new file mode 100644 index 000000000..24c6d9ab4 --- /dev/null +++ b/firmware/microblaze/apps/cruft/read_dbids.c @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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, see . + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + u2_init(); + + puts("\nread_dbids"); + + unsigned char dbid_tx[2]; + unsigned char dbid_rx[2]; + bool ok; + + ok = eeprom_read(I2C_ADDR_TX_A, 1, dbid_tx, 2); + if (!ok){ + puts("failed to read Tx Daugherboard EEPROM"); + } + else { + putstr("Tx Daugherboard ID: "); + puthex8(dbid_tx[1]); // MSB + puthex8(dbid_tx[0]); // LSB + newline(); + } + + ok = eeprom_read(I2C_ADDR_RX_A, 1, dbid_rx, 2); + if (!ok){ + puts("failed to read Rx Daugherboard EEPROM"); + } + else { + putstr("Rx Daugherboard ID: "); + puthex8(dbid_rx[1]); // MSB + puthex8(dbid_rx[0]); // LSB + newline(); + } + + return 0; +} diff --git a/firmware/microblaze/apps/cruft/sd_bounce.c b/firmware/microblaze/apps/cruft/sd_bounce.c new file mode 100644 index 000000000..c1b48f170 --- /dev/null +++ b/firmware/microblaze/apps/cruft/sd_bounce.c @@ -0,0 +1,153 @@ +/* + * Copyright 2007,2008 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, see . + */ + +/* + * Loopback SERDES to SERDES + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "nonstdio.h" +#include "memset_wa.h" +#include +#include +#include +#include +#include + + + +// ---------------------------------------------------------------- + +#define SERDES_RX_BUF_0 0 +#define SERDES_RX_BUF_1 1 + +/* + * ================================================================ + * configure SD RX double buffering state machine + * ================================================================ + */ + +// receive from SERDES +buf_cmd_args_t sd_recv_args = { + PORT_SERDES, + 0, + BP_LAST_LINE +}; + +// send to SERDES +buf_cmd_args_t sd_send_args = { + PORT_SERDES, + 0, // starts with packet in line 0 + 0, // filled in from list_line register +}; + +dbsm_t sd_sm; // the state machine + + + + +// ---------------------------------------------------------------- + +#if 0 +static bool +check_packet(int *buf, int nlines) +{ + bool ok = true; + int i = 0; + for (i = 0; i < nlines; i++){ + int expected = ((2*i + 0) << 16) | (2*i+1); + if (buf[i] != expected){ + ok = false; + printf("buf[%d] = 0x%x expected = 0x%x\n", i, buf[i], expected); + } + } + return ok; +} + +static void +zero_buffer(int bufno) +{ + memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4); +} +#endif + + +bool +sd_rx_inspector(dbsm_t *sm, int buf_this) +{ + hal_toggle_leds(0x2); + +#if 0 + int last_line = buffer_pool_status->last_line[buf_this]; + bool ok = check_packet(buffer_ram(buf_this), last_line); + static int good = 0; + static int bad = 0; + + if (ok) + good++; + else + bad++; + + if(good+bad == 10000) { + printf("Good %d\tBad %d\n",good,bad); + good = 0; + bad = 0; + } +#endif + + return false; +} + + +inline static void +buffer_irq_handler(void) +{ + uint32_t status = buffer_pool_status->status; + dbsm_process_status(&sd_sm, status); +} + + +int +main(void) +{ + u2_init(); + + putstr("\nsd_bounce\n"); + + // Get our clock from the mimo interface + clocks_mimo_config(MC_WE_LOCK_TO_MIMO); + + dbsm_init(&sd_sm, SERDES_RX_BUF_0, + &sd_recv_args, &sd_send_args, + sd_rx_inspector); + + // kick off the state machine + dbsm_start(&sd_sm); + + while(1){ + buffer_irq_handler(); + } +} diff --git a/firmware/microblaze/apps/cruft/sd_gentest.c b/firmware/microblaze/apps/cruft/sd_gentest.c new file mode 100644 index 000000000..35e912615 --- /dev/null +++ b/firmware/microblaze/apps/cruft/sd_gentest.c @@ -0,0 +1,269 @@ +/* + * Copyright 2007,2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "nonstdio.h" +#include "memset_wa.h" +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------- + +int packet_number = 0; +volatile bool send_packet_now = 0; + +#define SERDES_TX_BUF 0 +#define SERDES_RX_BUF 1 + + +#define NLINES_PER_PKT 380 + + +// ---------------------------------------------------------------- + +//static int timer_delta = (int)(MASTER_CLK_RATE * 100e-6); +static int timer_delta = 1000000; // .01 second + +void +timer_irq_handler(unsigned irq) +{ + hal_set_timeout(timer_delta); // schedule next timeout + send_packet_now = true; +} + + +static void +init_packet(int *buf) +{ + int i = 0; + for (i = 0; i < BP_NLINES; i++){ + buf[i] = ((2*i + 0) << 16) | (2*i+1); + } +} + +static bool +check_packet(int *buf, int nlines) +{ + bool ok = true; + int i = 0; + for (i = 0; i < nlines; i++){ + int expected = ((2*i + 0) << 16) | (2*i+1); + if (buf[i] != expected){ + ok = false; + printf("buf[%d] = 0x%x expected = 0x%x\n", i, buf[i], expected); + } + } + return ok; +} + +static void +zero_buffer(int bufno) +{ + memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4); +} + +static void +init_packets(void) +{ + // init just the one we're using + init_packet(buffer_ram(SERDES_TX_BUF)); +} + +int +main(void) +{ + u2_init(); + + // We're free running and provide clock to the MIMO interface + clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO); + + + // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output + // output_regs->debug_mux_ctrl = 1; + // hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + // hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + + putstr("\nsd_gentest\n"); + + // Set up serdes (already enabled) + //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN | SERDES_LOOPEN); + //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN); + + init_packets(); + + // pic_register_handler(IRQ_TIMER, timer_irq_handler); + + //if (hwconfig_simulation_p()) + // timer_delta = sim_timer_delta; + + // start a receive from sd + zero_buffer(SERDES_RX_BUF); + bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE); + + // fire off the first packet + bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT); + hal_set_timeout(timer_delta); + int ready_to_send = 0; + + int counter __attribute__((unused)) = 0; + int sent = 1; + int txerr = 0; + int rxerr = 0; + int rcvd = 0; + int rxcrc = 0; + int sent_acc = 0; + int txerr_acc = 0; + int rxerr_acc = 0; + int rcvd_acc = 0; + int rxcrc_acc = 0; + +#define EXPECTING_PKT() ((counter & 0x1) == 0) +#define SEND_PKT() ((counter & 0x1) != 0) + + bool got_packet = false; + + while(1){ + uint32_t status = buffer_pool_status->status; + + if (status & (BPS_DONE(SERDES_RX_BUF))){ + bp_clear_buf(SERDES_RX_BUF); + got_packet = true; + + //hal_toggle_leds(0x2); + + // check packet + int last_line = buffer_pool_status->last_line[SERDES_RX_BUF]-1; + bool ok = check_packet(buffer_ram(SERDES_RX_BUF), last_line); + + if (ok) { + rcvd++; + //putchar('r'); + } + else { + rcvd++; + rxcrc++; + //putchar('P'); + } + // start a receive from sd + zero_buffer(SERDES_RX_BUF); + bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE); + } + + if (status & (BPS_ERROR(SERDES_RX_BUF))){ + bp_clear_buf(SERDES_RX_BUF); + got_packet = true; + rcvd++; + rxerr++; + //putchar('E'); + + // start a receive from sd + zero_buffer(SERDES_RX_BUF); + bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE); + } + + if (status & (BPS_DONE(SERDES_TX_BUF))){ + bp_clear_buf(SERDES_TX_BUF); + //putchar('t'); + bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT); + //mdelay(1); + int i; + for (i = 0; i < 50; i++){ + asm volatile ("or r0, r0, r0\n\ + or r0, r0, r0\n \ + or r0, r0, r0\n \ + or r0, r0, r0\n \ + or r0, r0, r0\n \ + or r0, r0, r0\n \ + or r0, r0, r0\n"); + } + sent ++; + ready_to_send = 1; + //hal_toggle_leds(0x1); + } + + if (status & BPS_ERROR(SERDES_TX_BUF)){ + bp_clear_buf(SERDES_TX_BUF); + sent++; + txerr++; + ready_to_send = 1; + //putchar('X'); + } + + if(sent >=1000) { + printf("Status\tSENT %d\tTXERR %d\t",sent,txerr); + printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n",rcvd, rxerr, rxcrc, sent-rcvd); + sent_acc += sent; sent = 0; + txerr_acc += txerr; txerr = 0; + rcvd_acc += rcvd; rcvd = 0; + rxerr_acc += rxerr; rxerr = 0; + rxcrc_acc += rxcrc; rxcrc = 0; + } + + if(sent_acc >=10000) { + printf("\nOverall\tSENT %d\tTXERR %d\t",sent_acc,txerr_acc); + printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n\n",rcvd_acc, rxerr_acc, rxcrc_acc, sent_acc-rcvd_acc); + sent_acc = 0; + txerr_acc = 0; + rcvd_acc = 0; + rxerr_acc = 0; + rxcrc_acc = 0; + } +#if 0 + int pending = pic_regs->pending; + if (pending & PIC_TIMER_INT){ + hal_set_timeout(timer_delta); + + /* + if (EXPECTING_PKT()){ + if (!got_packet) + putchar('T'); + got_packet = false; + } + + if (SEND_PKT()){ + if (status & BPS_IDLE(SERDES_TX_BUF)) + bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT); + } + counter++; + */ + + putchar('T'); + if(ready_to_send) { + bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT); + counter++; + ready_to_send = 0; + } + + pic_regs->pending = PIC_TIMER_INT; // clear pending interrupt + } +#endif + } + + return 0; +} diff --git a/firmware/microblaze/apps/cruft/serdes_to_dsp.c b/firmware/microblaze/apps/cruft/serdes_to_dsp.c new file mode 100644 index 000000000..4994e0a69 --- /dev/null +++ b/firmware/microblaze/apps/cruft/serdes_to_dsp.c @@ -0,0 +1,179 @@ +/* + * Copyright 2007,2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "dbsm.h" +#include "app_common.h" +#include +#include +#include + + +/* + * This program can respond to queries from the host + * and stream rx samples. + * + * Buffer 1 is used by the cpu to send frames to the host. + * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow + * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow + */ +//#define CPU_RX_BUF 0 // eth -> cpu +//#define CPU_TX_BUF 1 // cpu -> eth + +#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer) +#define DSP_RX_BUF_1 3 // dsp rx -> eth +#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer) +#define DSP_TX_BUF_1 5 // eth -> dsp tx + +/* + * ================================================================ + * configure DSP TX double buffering state machine + * ================================================================ + */ + +// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) +// DSP Tx reads word0 (flags) + timestamp followed by samples + +#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) + +// Receive from ethernet +buf_cmd_args_t dsp_tx_recv_args = { + PORT_SERDES, + 0, + BP_LAST_LINE +}; + +// send to DSP Tx +buf_cmd_args_t dsp_tx_send_args = { + PORT_DSP, + DSP_TX_FIRST_LINE, // starts just past transport header + 0 // filled in from last_line register +}; + +dbsm_t dsp_tx_sm; // the state machine + + +// ---------------------------------------------------------------- + + +// The mac address of the host we're sending to. +eth_mac_addr_t host_mac_addr; + + +void +start_rx_cmd(const eth_mac_addr_t *host, op_start_rx_t *p) +{ +} + +void +stop_rx_cmd(void) +{ +} + +static void +setup_tx() +{ + dsp_tx_regs->clear_state = 1; + bp_clear_buf(DSP_TX_BUF_0); + bp_clear_buf(DSP_TX_BUF_1); + + int tx_scale = 256; + int interp = 32; + + op_config_tx_t def_config; + memset(&def_config, 0, sizeof(def_config)); + def_config.phase_inc = 408021893; // 9.5 MHz [2**32 * fc/fsample] + def_config.scale_iq = (tx_scale << 16) | tx_scale; + def_config.interp = interp; + + // setup Tx DSP regs + config_tx_cmd(&def_config); +} + + +inline static void +buffer_irq_handler(unsigned irq) +{ + //hal_toggle_leds(0x2); + + uint32_t status = buffer_pool_status->status; + + dbsm_process_status(&dsp_tx_sm, status); + + if (status & BPS_DONE(CPU_TX_BUF)){ + bp_clear_buf(CPU_TX_BUF); + } +} + +int +main(void) +{ + u2_init(); + + // Get our clock from the mimo interface + + clocks_enable_test_clk(true,1); + clocks_mimo_config(MC_WE_LOCK_TO_MIMO); + + // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output + //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + + putstr("\nserdes_to_dsp\n"); + + ethernet_register_link_changed_callback(link_changed_callback); + ethernet_init(); + + + // initialize double buffering state machine for ethernet -> DSP Tx + + dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, + &dsp_tx_recv_args, &dsp_tx_send_args, + eth_pkt_inspector); + + // program tx registers + setup_tx(); + + // kick off the state machine + dbsm_start(&dsp_tx_sm); + + while(1){ + buffer_irq_handler(0); + + int pending = pic_regs->pending; // poll for under or overrun + + if (pending & PIC_UNDERRUN_INT){ + dbsm_handle_tx_underrun(&dsp_tx_sm); + pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt + putchar('U'); + } + } +} + diff --git a/firmware/microblaze/apps/cruft/serdes_txrx.c b/firmware/microblaze/apps/cruft/serdes_txrx.c new file mode 100644 index 000000000..2c47c9628 --- /dev/null +++ b/firmware/microblaze/apps/cruft/serdes_txrx.c @@ -0,0 +1,368 @@ +/* + * Copyright 2007,2008,2009 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "dbsm.h" +#include "app_common_v2.h" +#include "memcpy_wa.h" +#include "clocks.h" +#include +#include +#include + + +#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) + +#if (FW_SETS_SEQNO) +static int fw_seqno; // used when f/w is filling in sequence numbers +#endif + + +/* + * Full duplex Tx and Rx between serdes and DSP pipelines + * + * Buffer 1 is used by the cpu to send frames to the host. + * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow + * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow + */ +//#define CPU_RX_BUF 0 // eth -> cpu + +#define DSP_RX_BUF_0 2 // dsp rx -> serdes (double buffer) +#define DSP_RX_BUF_1 3 // dsp rx -> serdes +#define DSP_TX_BUF_0 4 // serdes -> dsp tx (double buffer) +#define DSP_TX_BUF_1 5 // serdes -> dsp tx + +/* + * ================================================================== + * configure DSP TX double buffering state machine (serdes -> dsp) + * ================================================================== + */ + +// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) +// DSP Tx reads word0 (flags) + timestamp followed by samples + +#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) + +// Receive from serdes +buf_cmd_args_t dsp_tx_recv_args = { + PORT_SERDES, + 0, + BP_LAST_LINE +}; + +// send to DSP Tx +buf_cmd_args_t dsp_tx_send_args = { + PORT_DSP, + DSP_TX_FIRST_LINE, // starts just past transport header + 0 // filled in from last_line register +}; + +dbsm_t dsp_tx_sm; // the state machine + +/* + * ================================================================= + * configure DSP RX double buffering state machine (dsp -> serdes) + * ================================================================= + */ + +// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0) +// DSP Rx writes timestamp followed by nlines_per_frame of samples +#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1) + +// receive from DSP +buf_cmd_args_t dsp_rx_recv_args = { + PORT_DSP, + DSP_RX_FIRST_LINE, + BP_LAST_LINE +}; + +// send to serdes +buf_cmd_args_t dsp_rx_send_args = { + PORT_SERDES, + 0, // starts with ethernet header in line 0 + 0, // filled in from list_line register +}; + +dbsm_t dsp_rx_sm; // the state machine + + +// The mac address of the host we're sending to. +eth_mac_addr_t host_mac_addr; + + +// variables for streaming mode + +static bool streaming_p = false; +static unsigned int streaming_items_per_frame = 0; +static int streaming_frame_count = 0; +#define FRAMES_PER_CMD 1000 + +bool is_streaming(void){ return streaming_p; } + +// ---------------------------------------------------------------- + + +void +restart_streaming(void) +{ + // setup RX DSP regs + dsp_rx_regs->clear_state = 1; // reset + + streaming_p = true; + streaming_frame_count = FRAMES_PER_CMD; + + dsp_rx_regs->rx_command = + MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, + streaming_items_per_frame, + 1, 1); // set "chain" bit + + // kick off the state machine + dbsm_start(&dsp_rx_sm); + + dsp_rx_regs->rx_time = 0; // enqueue first of two commands + + // make sure this one and the rest have the "now" and "chain" bits set. + dsp_rx_regs->rx_command = + MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, + streaming_items_per_frame, + 1, 1); + + dsp_rx_regs->rx_time = 0; // enqueue second command +} + +void +start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p) +{ + host_mac_addr = *host; // remember who we're sending to + + /* + * Construct ethernet header and word0 and preload into two buffers + */ + u2_eth_packet_t pkt; + memset(&pkt, 0, sizeof(pkt)); + pkt.ehdr.dst = *host; + pkt.ehdr.src = *ethernet_mac_addr(); + pkt.ehdr.ethertype = U2_ETHERTYPE; + u2p_set_word0(&pkt.fixed, 0, 0); + // DSP RX will fill in timestamp + + memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt)); + memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt)); + + + if (FW_SETS_SEQNO) + fw_seqno = 0; + + streaming_items_per_frame = p->items_per_frame; + restart_streaming(); +} + + +void +stop_rx_cmd(void) +{ + streaming_p = false; + dsp_rx_regs->clear_state = 1; // flush cmd queue + bp_clear_buf(DSP_RX_BUF_0); + bp_clear_buf(DSP_RX_BUF_1); +} + + +static void +setup_tx() +{ + dsp_tx_regs->clear_state = 1; + bp_clear_buf(DSP_TX_BUF_0); + bp_clear_buf(DSP_TX_BUF_1); + + int tx_scale = 256; + int interp = 32; + + // setup some defaults + + dsp_tx_regs->freq = 0; + dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; + dsp_tx_regs->interp_rate = interp; +} + + +#if (FW_SETS_SEQNO) +/* + * Debugging ONLY. This will be handled by the tx_protocol_engine. + * + * This is called when the DSP Rx chain has filled in a packet. + * We set and increment the seqno, then return false, indicating + * that we didn't handle the packet. A bit of a kludge + * but it should work. + */ +bool +fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false +{ + uint32_t *p = buffer_ram(buf_this); + uint32_t seqno = fw_seqno++; + + // KLUDGE all kinds of nasty magic numbers and embedded knowledge + uint32_t t = p[4]; + t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); + p[4] = t; + + // queue up another rx command when required + if (streaming_p && --streaming_frame_count == 0){ + streaming_frame_count = FRAMES_PER_CMD; + dsp_rx_regs->rx_time = 0; + } + + return false; // we didn't handle the packet +} +#endif + + +inline static void +buffer_irq_handler(unsigned irq) +{ + // hal_toggle_leds(LED_A); + + uint32_t status = buffer_pool_status->status; + + if (0 && (status & ~BPS_IDLE_ALL)){ + putstr("status = "); + puthex32_nl(status); + } + + dbsm_process_status(&dsp_tx_sm, status); + dbsm_process_status(&dsp_rx_sm, status); +} + +int +main(void) +{ + u2_init(); + + output_regs->led_src = 0x3; // h/w controls bottom two bits + clocks_enable_test_clk(true, 1); + + putstr("\nSERDES TxRx\n"); + + cpu_tx_buf_dest_port = PORT_SERDES; + + // ethernet_register_link_changed_callback(link_changed_callback); + // ethernet_init(); + + clocks_mimo_config(MC_WE_LOCK_TO_MIMO); + + // puts("post clocks_mimo_config"); + +#if 0 + // make bit 15 of Tx gpio's be a s/w output + hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); + hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); +#endif + +#if 0 + output_regs->debug_mux_ctrl = 1; + hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000"); + hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000"); + hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); + hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); +#endif + + + // initialize double buffering state machine for ethernet -> DSP Tx + + dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, + &dsp_tx_recv_args, &dsp_tx_send_args, + eth_pkt_inspector); + + + //output_regs->flush_icache = 1; + + // initialize double buffering state machine for DSP RX -> Ethernet + + if (FW_SETS_SEQNO){ + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + fw_sets_seqno_inspector); + } + else { + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + dbsm_nop_inspector); + } + + // puts("post dbsm_init's"); + + // tell app_common that this dbsm could be sending to the ethernet + ac_could_be_sending_to_eth = &dsp_rx_sm; + + + // program tx registers + setup_tx(); + + // puts("post setup_tx"); + + // kick off the state machine + dbsm_start(&dsp_tx_sm); + + // puts("post dbsm_start"); + + //int which = 0; + + while(1){ + // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); + // which ^= 0x8000; + + buffer_irq_handler(0); + + int pending = pic_regs->pending; // poll for under or overrun + + if (pending & PIC_UNDERRUN_INT){ + dbsm_handle_tx_underrun(&dsp_tx_sm); + pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt + putchar('U'); + } + + if (pending & PIC_OVERRUN_INT){ + dbsm_handle_rx_overrun(&dsp_rx_sm); + pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt + + // FIXME Figure out how to handle this robustly. + // Any buffers that are emptying should be allowed to drain... + + if (streaming_p){ + // restart_streaming(); + // FIXME report error + } + else { + // FIXME report error + } + putchar('O'); + } + } +} diff --git a/firmware/microblaze/apps/cruft/set_hw_rev.c b/firmware/microblaze/apps/cruft/set_hw_rev.c new file mode 100644 index 000000000..d4ac8ff81 --- /dev/null +++ b/firmware/microblaze/apps/cruft/set_hw_rev.c @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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, see . + */ +#include +#include +#include +#include + +#define HW_REV_MAJOR 0 +#define HW_REV_MINOR 3 + +int +main(void) +{ + u2_init(); + + putstr("\nset_hw_rev\n"); + + bool ok = true; + unsigned char maj = HW_REV_MAJOR; + unsigned char min = HW_REV_MINOR; + ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1); + ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1); + + if (ok) + printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); + else + printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); + + return 0; +} diff --git a/firmware/microblaze/apps/cruft/test1.c b/firmware/microblaze/apps/cruft/test1.c new file mode 100644 index 000000000..c3cc3be56 --- /dev/null +++ b/firmware/microblaze/apps/cruft/test1.c @@ -0,0 +1,282 @@ +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include "nonstdio.h" + +// Globals +#define EMPTY 0 +#define FILLING 1 +#define FULL 2 +#define EMPTYING 3 + +#define PORT 2 // ethernet = 2, serdes = 0 +int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf; +int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle; + +int buffer_state[4]; + + +void double_buffering(int port); + +// +// We register this in the secondary interrupt vector. +// It's called on buffer manager interrupts +// +void +buffer_irq_handler(unsigned irq) +{ + double_buffering(PORT); +} + +int +main(void) +{ + int i; + + u2_init(); + + // Control LEDs + output_regs->leds = 0x02; + + // Turn on ADCs + output_regs->adc_ctrl = 0x0A; + + // Set up TX Chain + dsp_tx_regs->freq = 0; + dsp_tx_regs->scale_iq = (1 << 16) | 1; + dsp_tx_regs->interp_rate = 8; + + // Set up RX Chain + dsp_rx_regs->freq = 0; + dsp_rx_regs->scale_iq = (1 << 16) | 1; + dsp_rx_regs->decim_rate = 8; + + // Set up buffer control, using only 4 for now + for(i=0;i<4;i++) + buffer_state[i] = EMPTY; + + // Set up DSP RX + buffer_state[0] = FILLING; + serdes_tx_idle = 1; + bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines + + //dsp_rx_regs->run_rx = 1; // Start DSP_RX + putstr("Done DSP RX setup\n"); + + // Set up serdes RX + buffer_state[2] = FILLING; + dsp_tx_idle = 1; + bp_receive_to_buf(2, PORT, 1, 5, 504); + + while (buffer_pool_status->status == 0) // wait for completion of DSP RX + ; + + putstr("Done DSP TX setup\n"); + //dsp_tx_regs->run_tx = 1; + + // register interrupt handler + pic_register_handler(IRQ_BUFFER, buffer_irq_handler); + + while (1) + ; + + hal_finish(); + return 1; +} + +void +double_buffering(int port) { + unsigned int localstatus = buffer_pool_status->status; + + if(localstatus & BPS_DONE_0) { + bp_clear_buf(0); + if(buffer_state[0] == FILLING) { + buffer_state[0] = FULL; + if(buffer_state[1] == EMPTY) { + bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines + buffer_state[1] = FILLING; + } + else + dsp_rx_idle = 1; + if(serdes_tx_idle) { + serdes_tx_idle = 0; + bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0 + buffer_state[0] = EMPTYING; + } + } + else { // buffer was emptying + buffer_state[0] = EMPTY; + if(dsp_rx_idle) { + dsp_rx_idle = 0; + bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines + buffer_state[0] = FILLING; + } + if(buffer_state[1] == FULL) { + bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1 + buffer_state[1] = EMPTYING; + } + else + serdes_tx_idle = 1; + } + putstr("Int Proc'ed 0\n"); + } + if(localstatus & BPS_DONE_1) { + bp_clear_buf(1); + if(buffer_state[1] == FILLING) { + buffer_state[1] = FULL; + if(buffer_state[0] == EMPTY) { + bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines + buffer_state[0] = FILLING; + } + else + dsp_rx_idle = 1; + if(serdes_tx_idle) { + serdes_tx_idle = 0; + bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1 + buffer_state[1] = EMPTYING; + } + } + else { // buffer was emptying + buffer_state[1] = EMPTY; + if(dsp_rx_idle) { + dsp_rx_idle = 0; + bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines + buffer_state[1] = FILLING; + } + if(buffer_state[0] == FULL) { + bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0 + buffer_state[0] = EMPTYING; + } + else + serdes_tx_idle = 1; + } + putstr("Int Proc'ed 1\n"); + } + if(localstatus & BPS_DONE_2) { + bp_clear_buf(2); + if(buffer_state[2] == FILLING) { + buffer_state[2] = FULL; + if(buffer_state[3] == EMPTY) { + bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3, use 500 lines + buffer_state[3] = FILLING; + } + else + serdes_rx_idle = 1; + if(dsp_tx_idle) { + dsp_tx_idle = 0; + bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2 + buffer_state[2] = EMPTYING; + } + } + else { // buffer was emptying + buffer_state[2] = EMPTY; + if(serdes_rx_idle) { + serdes_rx_idle = 0; + bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2 + buffer_state[2] = FILLING; + } + if(buffer_state[3] == FULL) { + bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3 + buffer_state[3] = EMPTYING; + } + else + dsp_tx_idle = 1; + } + putstr("Int Proc'ed 2\n"); + } + if(localstatus & BPS_DONE_3) { + bp_clear_buf(3); + if(buffer_state[3] == FILLING) { + buffer_state[3] = FULL; + if(buffer_state[2] == EMPTY) { + bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2, use 500 lines + buffer_state[2] = FILLING; + } + else + serdes_rx_idle = 1; + if(dsp_tx_idle) { + dsp_tx_idle = 0; + bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3 + buffer_state[3] = EMPTYING; + } + } + else { // buffer was emptying + buffer_state[3] = EMPTY; + if(serdes_rx_idle) { + serdes_rx_idle = 0; + bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3 + buffer_state[3] = FILLING; + } + if(buffer_state[2] == FULL) { + bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2 + buffer_state[2] = EMPTYING; + } + else + dsp_tx_idle = 1; + } + putstr("Int Proc'ed 3\n"); + } +} + +// Spare Code + +#if 0 + // Set up LSDAC + int i = 0; + while(1) { + int command = (3 << 19) | (0 << 16) | (i & 0xffff); + spi_transact(SPI_TXONLY, SPI_SS_TX_DAC, command, 24, 1); // negate TX phase + i++; + } +#endif + +#if 0 + // Write to buffer 0 + int *buf = (int *)(BUFFER_BASE + BUFFER_0); + puthex_nl((int)buf); + + for(i=0;i. + */ + +#include +#include +#include +#include + +int +main(void) +{ + u2_init(); + + puts("\ntest_db_spi"); + + while(1){ + spi_transact(SPI_TXONLY, SPI_SS_RX_DB, 0xCC33, 16, SPIF_PUSH_FALL); + spi_transact(SPI_TXONLY, SPI_SS_TX_DB, 0x33CC, 16, SPIF_PUSH_FALL); + } +} diff --git a/firmware/microblaze/apps/cruft/test_i2c.c b/firmware/microblaze/apps/cruft/test_i2c.c new file mode 100644 index 000000000..f349ead88 --- /dev/null +++ b/firmware/microblaze/apps/cruft/test_i2c.c @@ -0,0 +1,108 @@ +/* + * Copyright 2007 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, see . + */ + +#include +#include +#include /* FIXME */ +#include +#include +#include +#include + + + +#define ASSERT_TRUE(x) \ + do { \ + if (!(x)){ \ + printf("ASSERT_TRUE failed on line %d\n", __LINE__); \ + nerrors++; \ + } \ + } while(0) + +#define ASSERT_FALSE(x) \ + do { \ + if (x){ \ + printf("ASSERT_FALSE failed on line %d\n", __LINE__); \ + nerrors++; \ + } \ + } while(0) + + +#define BUFSIZE 128 + +int +main(void) +{ + int i; + bool ok; + int nerrors = 0; + uint8_t buf[BUFSIZE]; + int not_dev_addr = 0x35; // no device with this address on the i2c bus. + int offset; + int len; + + u2_init(); + + puts("test_i2c\n"); + + // try writing a non-existent device + buf[0] = 0xA5; + ok = i2c_write(not_dev_addr, buf, 1); + ASSERT_FALSE(ok); + + // try read from non-existent device + buf[0] = 0; + ok = i2c_read(not_dev_addr, buf, 1); + ASSERT_FALSE(ok); + + // try writing eeprom + offset = 31; + len = 8; + memset(buf, 0, sizeof(buf)); + for (i = 0; i < len; i++) + buf[i] = i; + ok = eeprom_write(I2C_ADDR_MBOARD, offset, buf, len); + ASSERT_TRUE(ok); + + // now try to read it back + offset = 31; + len = 8; + memset(buf, 0, sizeof(buf)); + ok = eeprom_read(I2C_ADDR_MBOARD, offset, buf, len); + ASSERT_TRUE(ok); + + // check result + for (i = 0; i < len; i++){ + if (buf[i] != i){ + printf("buf[%d] = %d, should be %d\n", i, buf[i], i); + nerrors++; + } + } + + if (nerrors == 0){ + output_regs->leds = 0x3; + puts("PASSED\n"); + } + else { + output_regs->leds = 0x0; + puts("FAILED\n"); + } + + hal_finish(); + return 0; +} + diff --git a/firmware/microblaze/apps/cruft/test_lsadc.c b/firmware/microblaze/apps/cruft/test_lsadc.c new file mode 100644 index 000000000..5fda29cd7 --- /dev/null +++ b/firmware/microblaze/apps/cruft/test_lsadc.c @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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, see . + */ + +#include +#include +#include +#include +#include + +int +main(void) +{ + u2_init(); + + puts("\ntest_lsadc"); + + uint32_t r; + + unsigned int up_counter = 0; + + while (1){ + unsigned int v; + v = up_counter; + + lsdac_write_rx(0, v << 0); + lsdac_write_rx(2, v << 1); + +#if 1 + r = lsadc_read_rx(0); + lsdac_write_rx(1, r & 0x0fff); + //puthex32_nl(r); +#endif + +#if 1 + r = lsadc_read_rx(1); + lsdac_write_rx(3, r & 0x0fff); + //puthex32_nl(r); +#endif + + up_counter++; + } +} diff --git a/firmware/microblaze/apps/cruft/test_lsdac.c b/firmware/microblaze/apps/cruft/test_lsdac.c new file mode 100644 index 000000000..8c1bf333b --- /dev/null +++ b/firmware/microblaze/apps/cruft/test_lsdac.c @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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, see . + */ + +#include +#include +#include +#include + +int +main(void) +{ + u2_init(); + + puts("\ntest_lsdac"); + + unsigned int up_counter = 0; + unsigned int dn_counter = 0; + + while(1){ + unsigned int v; + v = up_counter; + lsdac_write_rx(0, v << 0); + lsdac_write_rx(1, v << 1); + lsdac_write_rx(2, v << 2); + lsdac_write_rx(3, v << 3); + + v = up_counter; + lsdac_write_tx(0, v << 0); + lsdac_write_tx(1, v << 1); + lsdac_write_tx(2, v << 2); + lsdac_write_tx(3, v << 3); + + up_counter++; + dn_counter--; + } +} diff --git a/firmware/microblaze/apps/cruft/test_phy_comm.c b/firmware/microblaze/apps/cruft/test_phy_comm.c new file mode 100644 index 000000000..d312ca4cc --- /dev/null +++ b/firmware/microblaze/apps/cruft/test_phy_comm.c @@ -0,0 +1,113 @@ +/* + * Copyright 2007 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, see . + */ + +// check communication with ethernet PHY chip + +#include "u2_init.h" +#include "memory_map.h" +#include "hal_io.h" +#include "ethernet.h" +#include "pic.h" +#include "nonstdio.h" + + +#define DELTA_T 12500000 // .125s (10ns per tick) +//#define DELTA_T 10000 + +// debugging output on tx pins +#define LS_MASK 0xE0000 +#define LS_1000 0x80000 +#define LS_100 0x40000 +#define LS_10 0x20000 + + + +#define U2_ETHERTYPE 0xBEEF + + +static volatile int led_link_up_flag = 0; + +/* + * Called when eth phy state changes (w/ interrupts disabled) + */ +void +link_changed_callback(int speed) +{ + int v = 0; + switch(speed){ + case 10: + v = LS_10; + led_link_up_flag = 0x2; + break; + + case 100: + v = LS_100; + led_link_up_flag = 0x2; + break; + + case 1000: + v = LS_100; + led_link_up_flag = 0x2; + break; + + default: + v = 0; + led_link_up_flag = 0; + break; + } + + //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */ + + putstr("\neth link changed: speed = "); + puthex_nl(speed); +} + +void +timer_handler(unsigned irq) +{ + static int led_counter = 0; + + hal_set_timeout(DELTA_T); // schedule next timeout + output_regs->leds = (led_counter++ & 0x1) | led_link_up_flag; +} + +int +main(void) +{ + u2_init(); + + putstr("\n test_phy_comm\n"); + + pic_register_handler(IRQ_ONETIME, timer_handler); + hal_set_timeout(DELTA_T); // schedule timeout + + // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output + //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + + ethernet_register_link_changed_callback(link_changed_callback); + + output_regs->phy_ctrl = 1; /* reset the eth PHY */ + output_regs->phy_ctrl = 0; + + ethernet_init(); + + while(1) + ; + + return 0; +} diff --git a/firmware/microblaze/apps/cruft/test_ram.c b/firmware/microblaze/apps/cruft/test_ram.c new file mode 100644 index 000000000..77ee693f6 --- /dev/null +++ b/firmware/microblaze/apps/cruft/test_ram.c @@ -0,0 +1,105 @@ +/* + * Copyright 2007 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, see . + */ + +#include +#include +#include /* FIXME */ +#include +#include +#include +#include +#include + +#define ASSERT_TRUE(x) \ + do { \ + if (!(x)){ \ + printf("ASSERT_TRUE failed on line %d\n", __LINE__); \ + nerrors++; \ + } \ + } while(0) + +#define ASSERT_FALSE(x) \ + do { \ + if (x){ \ + printf("ASSERT_FALSE failed on line %d\n", __LINE__); \ + nerrors++; \ + } \ + } while(0) + + +#define BUFSIZE 128 + +int test_ram() +{ + int i,j,k; + output_regs->ram_page = 1<<10; + + extram[0] = 0xDEADBEEF; + extram[1] = 0xF00D1234; + extram[7] = 0x76543210; + + output_regs->ram_page = 2<<10; + extram[7] = 0x55555555; + extram[1] = 0xaaaaaaaa; + extram[0] = 0xeeeeeeee; + + output_regs->ram_page = 1<<10; + + i = extram[0]; + k = extram[1]; + j = extram[7]; + + if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { + puts("RAM FAIL1!\n"); + puthex32_nl(i); + puthex32_nl(j); + puthex32_nl(k); + return 0; + } + + output_regs->ram_page = 2<<10; + + j = extram[7]; + k = extram[1]; + i = extram[0]; + + if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { + puts("RAM FAIL2!\n"); + puthex32_nl(i); + puthex32_nl(j); + puthex32_nl(k); + return 0; + } + return 1; +} + +int +main(void) +{ + + u2_init(); + puts("\ntest_ram\n"); + int success = test_ram(); + if(success) + puts("RAM Passed Tests\n"); + else + puts("RAM Failed\n"); + + hal_finish(); + return 0; +} + diff --git a/firmware/microblaze/apps/cruft/test_sd.c b/firmware/microblaze/apps/cruft/test_sd.c new file mode 100644 index 000000000..494432d7f --- /dev/null +++ b/firmware/microblaze/apps/cruft/test_sd.c @@ -0,0 +1,81 @@ +/* + * Copyright 2007 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, see . + */ + +#include +#include +#include /* FIXME */ +#include +#include +#include +#include + + +#define ASSERT_TRUE(x) \ + do { \ + if (!(x)){ \ + printf("ASSERT_TRUE failed on line %d\n", __LINE__); \ + nerrors++; \ + } \ + } while(0) + +#define ASSERT_FALSE(x) \ + do { \ + if (x){ \ + printf("ASSERT_FALSE failed on line %d\n", __LINE__); \ + nerrors++; \ + } \ + } while(0) + + +#define BUFSIZE 128 + +int +main(void) +{ + int i; + unsigned char buf[512]; + + u2_init(); + + puts("\ntest_sd\n"); + + + i = sd_init(); + if(i) + puts("Successfully Init'ed Card\n"); + else + puts("FAILED INIT of Card\n"); + + i = sd_read_block(2048,buf); + if(i) { + puts("READ Command accepted\n"); + for(i=0;i<512;i++) + if((i&15) == 15) + puthex8_nl(buf[i]); + else { + puthex8(buf[i]); + putchar(' '); + } + } + else + puts("READ Command Rejected\n"); + + puts("Done"); + hal_finish(); + return 0; +} + diff --git a/firmware/microblaze/apps/cruft/timer_test.c b/firmware/microblaze/apps/cruft/timer_test.c new file mode 100644 index 000000000..44e80b5f1 --- /dev/null +++ b/firmware/microblaze/apps/cruft/timer_test.c @@ -0,0 +1,57 @@ +/* + * Copyright 2007 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, see . + */ + +#include "u2_init.h" +#include "memory_map.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include "nonstdio.h" +#include "hal_io.h" + +#define DELTA_T 500 // 5 us (10ns per tick) + + +void +timer_handler(unsigned irq) +{ + hal_set_timeout(DELTA_T); + + putstr("Tick: "); + puthex_nl(0); +} + +int +main(void) +{ + u2_init(); + + // setup timer + + putstr("Setting up timer\n"); + pic_register_handler(IRQ_ONETIME, timer_handler); + + hal_set_timeout(DELTA_T); + + while (1) + ; + + putstr("Done Testing\n"); + + hal_finish(); + return 1; +} diff --git a/firmware/microblaze/apps/cruft/tx_standalone.c b/firmware/microblaze/apps/cruft/tx_standalone.c new file mode 100644 index 000000000..1645fa8ba --- /dev/null +++ b/firmware/microblaze/apps/cruft/tx_standalone.c @@ -0,0 +1,339 @@ +/* + * Copyright 2007 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "buffer_pool.h" +#include "pic.h" +#include +#include "ethernet.h" +#include "nonstdio.h" +#include "usrp2_eth_packet.h" +#include "memcpy_wa.h" +#include "dbsm.h" +#include +#include +#include + +#define _AL4 __attribute__((aligned (4))) + +#define USE_BUFFER_INTERRUPT 0 // 0 or 1 + + +static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz + +/* + * This program can respond to queries from the host + * and stream rx samples. + * + * Buffer 1 is used by the cpu to send frames to the host. + * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow + * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow + */ +//#define CPU_RX_BUF 0 // eth -> cpu +#define CPU_TX_BUF 1 // cpu -> eth + +#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer) +#define DSP_RX_BUF_1 3 // dsp rx -> eth +#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer) +#define DSP_TX_BUF_1 5 // eth -> dsp tx + + +/* + * ================================================================ + * configure DSP RX double buffering state machine + * ================================================================ + */ + + +// 4 lines of ethernet hdr + 1 line (word0) +// DSP Rx writes timestamp followed by nlines_per_frame of samples +#define DSP_RX_FIRST_LINE 5 +#define DSP_RX_SAMPLES_PER_FRAME 128 +#define DSP_RX_EXTRA_LINES 1 // writes timestamp + +// Receive from DSP Rx +buf_cmd_args_t dsp_rx_recv_args = { + PORT_DSP, + DSP_RX_FIRST_LINE, + BP_LAST_LINE +}; + +// send to ethernet +buf_cmd_args_t dsp_rx_send_args = { + PORT_ETH, + 0, // starts with ethernet header in line 0 + 0, // filled in from last_line register +}; + +dbsm_t dsp_rx_sm; // the state machine + +/* + * ================================================================ + * configure DSP TX double buffering state machine + * ================================================================ + */ + +// 4 lines of ethernet hdr + 2 lines (word0 + timestamp) +// DSP Tx reads word0 (flags) + timestamp followed by samples + +#define DSP_TX_FIRST_LINE 4 +#define DSP_TX_SAMPLES_PER_FRAME 250 // not used except w/ debugging +#define DSP_TX_EXTRA_LINES 2 // reads word0 + timestamp + +// Receive from ethernet +buf_cmd_args_t dsp_tx_recv_args = { + PORT_ETH, + 0, + BP_LAST_LINE +}; + +// send to DSP Tx +buf_cmd_args_t dsp_tx_send_args = { + PORT_DSP, + DSP_TX_FIRST_LINE, // starts just past ethernet header + 0 // filled in from last_line register +}; + +dbsm_t dsp_tx_sm; // the state machine + +/* + * send constant buffer to DSP TX + */ +static inline void +SEND_CONST_TO_DSP_TX(void) +{ + bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, + DSP_TX_FIRST_LINE, + DSP_TX_FIRST_LINE + DSP_TX_EXTRA_LINES + DSP_TX_SAMPLES_PER_FRAME - 1); +} + +// ---------------------------------------------------------------- + + + +// The mac address of the host we're sending to. +eth_mac_addr_t host_mac_addr; + + +void link_changed_callback(int speed); +static volatile bool link_is_up = false; // eth handler sets this + + +void +timer_irq_handler(unsigned irq) +{ + hal_set_timeout(timer_delta); // schedule next timeout +} + +// Tx DSP underrun +void +underrun_irq_handler(unsigned irq) +{ + dsp_tx_regs->clear_state = 1; + bp_clear_buf(DSP_TX_BUF_0); + bp_clear_buf(DSP_TX_BUF_1); + dbsm_stop(&dsp_tx_sm); + + // FIXME anything else? + + putstr("\nirq: underrun\n"); +} + +// Rx DSP overrun +void +overrun_irq_handler(unsigned irq) +{ + dsp_rx_regs->clear_state = 1; + bp_clear_buf(DSP_RX_BUF_0); + bp_clear_buf(DSP_RX_BUF_1); + dbsm_stop(&dsp_rx_sm); + + // FIXME anything else? + + putstr("\nirq: overrun\n"); +} + +static void +start_tx_transfers(void) +{ + bp_clear_buf(DSP_TX_BUF_0); // FIXME, really goes in state machine + bp_clear_buf(DSP_TX_BUF_1); + + // fill everything with a constant 32k + 0j + + uint32_t const_sample = (32000 << 16) | 0; + int i; + for (i = 0; i < BP_NLINES; i++){ + buffer_ram(DSP_TX_BUF_0)[i] = const_sample; + buffer_ram(DSP_TX_BUF_1)[i] = const_sample; + } + + /* + * Construct ethernet header and word0 and preload into two buffers + */ + u2_eth_packet_t pkt; + memset(&pkt, 0, sizeof(pkt)); + //pkt.ehdr.dst = *host; + pkt.ehdr.src = *ethernet_mac_addr(); + pkt.ehdr.ethertype = U2_ETHERTYPE; + u2p_set_word0(&pkt.fixed, + U2P_TX_IMMEDIATE | U2P_TX_START_OF_BURST, 0); + u2p_set_timestamp(&pkt.fixed, T_NOW); + + memcpy_wa(buffer_ram(DSP_TX_BUF_0), &pkt, sizeof(pkt)); + memcpy_wa(buffer_ram(DSP_TX_BUF_1), &pkt, sizeof(pkt)); + + + int tx_scale = 256; + + // setup Tx DSP regs + dsp_tx_regs->clear_state = 1; // reset + dsp_tx_regs->freq = 408021893; // 9.5 MHz [2**32 * fc/fsample] + dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; + dsp_tx_regs->interp_rate = 32; + + // kick off the state machine + // dbsm_start(&dsp_rx_sm); + + SEND_CONST_TO_DSP_TX(); // send constant buffer to DSP TX +} + + +void +buffer_irq_handler(unsigned irq) +{ + uint32_t status = buffer_pool_status->status; + + if (0){ + putstr("irq: "); + puthex32(status); + putchar('\n'); + } + + if (status & BPS_ERROR_ALL){ + // FIXME rare path, handle error conditions + } + + if (status & BPS_DONE(DSP_TX_BUF_0)){ + bp_clear_buf(DSP_TX_BUF_0); + SEND_CONST_TO_DSP_TX(); + hal_toggle_leds(0x1); + } + +} + +int +main(void) +{ + u2_init(); + + // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output + //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); + //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); + + putstr("\ntx_only\n"); + + // Control LEDs + hal_set_leds(0x0, 0x3); + + if (USE_BUFFER_INTERRUPT) + pic_register_handler(IRQ_BUFFER, buffer_irq_handler); + + pic_register_handler(IRQ_OVERRUN, overrun_irq_handler); + pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler); + + //pic_register_handler(IRQ_TIMER, timer_irq_handler); + //hal_set_timeout(timer_delta); + + ethernet_register_link_changed_callback(link_changed_callback); + + ethernet_init(); + + // initialize double buffering state machine for DSP RX -> Ethernet + dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, + &dsp_rx_recv_args, &dsp_rx_send_args, + dbsm_nop_inspector); + + // setup receive from ETH + // bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE); + +#if 0 + if (hwconfig_simulation_p()){ + // If we're simulating, pretend that we got a start command from the host + eth_mac_addr_t host = {{ 0x00, 0x0A, 0xE4, 0x3E, 0xD2, 0xD5 }}; + start_rx_cmd(&host); + } +#endif + + start_tx_transfers(); // send constant buffers to DSP TX + + while(1){ + if (!USE_BUFFER_INTERRUPT) + buffer_irq_handler(0); + } +} + +// ---------------------------------------------------------------- + +// debugging output on tx pins +#define LS_MASK 0xE0000 +#define LS_1000 0x80000 +#define LS_100 0x40000 +#define LS_10 0x20000 + +/* + * Called when eth phy state changes (w/ interrupts disabled) + */ +void +link_changed_callback(int speed) +{ + int v = 0; + switch(speed){ + case 10: + v = LS_10; + link_is_up = true; + break; + + case 100: + v = LS_100; + link_is_up = true; + break; + + case 1000: + v = LS_100; + link_is_up = true; + break; + + default: + v = 0; + link_is_up = false; + break; + } + + //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */ + + // hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2); + + printf("\neth link changed: speed = %d\n", speed); +} diff --git a/firmware/microblaze/apps/flash_test.c b/firmware/microblaze/apps/flash_test.c new file mode 100644 index 000000000..5b4569030 --- /dev/null +++ b/firmware/microblaze/apps/flash_test.c @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//just a test to write to SPI flash and retrieve the same values. +//uses the MOBFLEET SPI flash library + +void delay(uint32_t t) { + while(t-- != 0) asm("NOP"); +} + +int main(int argc, char *argv[]) { + uint16_t i, t; + uint8_t buf[260]; + const uint8_t testdata[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C}; + + hal_disable_ints(); // In case we got here via jmp 0x0 +// spi_init(); + hal_uart_init(); +// clocks_init(); //set up AD9510, enable FPGA clock @ 1x divisor + + puts("SPI Flash test\n"); + puts("Initializing SPI\n"); + + spif_init(); + delay(800000); + puts("Erasing sector 1\n"); + spi_flash_erase(0x00010000, 256); + delay(800000); + puts("Reading back data\n"); + spi_flash_read(0x00010000, 256, buf); + delay(800000); + + t=1; + for(i=4; i<250; i++) { + if(buf[i] != 0xFF) t=0; + } + + if(!t) puts("Data was not initialized to 0xFF. Unsuccessful erase or read\n"); + else puts("Data initialized to 0xFF, erase confirmed\n"); + + puts("Writing test buffer\n"); + spi_flash_program(0x00010000, 16, testdata); + //memset(buf, 0, 256); + + delay(800000); + puts("Wrote data, reading back\n"); + + spi_flash_read(0x00010000, 16, buf); + + if(memcmp(testdata, buf, 16)) puts("Data is not the same between read and write. Unsuccessful write or read\n"); + else puts("Successful write! Flash write correct\n"); + + return 0; +} diff --git a/firmware/microblaze/apps/hardware_testbed.c b/firmware/microblaze/apps/hardware_testbed.c new file mode 100644 index 000000000..e68e68ff7 --- /dev/null +++ b/firmware/microblaze/apps/hardware_testbed.c @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include + +//so this is just an evolving file used to set up and test different bits of hardware (EEPROM, clock chip, A/D, D/A, PHY) +void delay(uint32_t t) { + while(t-- != 0) asm("NOP"); +} + +int main(int argc, char *argv[]) { + + hal_disable_ints(); + hal_uart_init(); + spi_init(); + + puts("Hardware testbed. Init clocks..."); + + clocks_init(); + + //now, hopefully, we should be running at 100MHz instead of 50MHz, meaning our UART is twice as fast and we're talking at 230400. + + while(1) { + delay(500000); + puts("Eat at Joe's."); + } + + + + + + return 0; +} diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index f7f140121..4e03bc869 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -41,7 +41,6 @@ #include #include #include "clocks.h" -#include #include "usrp2/fw_common.h" #include #include @@ -266,7 +265,7 @@ void handle_udp_ctrl_packet( * Peek and Poke Register ******************************************************************/ case USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO: - if (ctrl_data_in->data.poke_args.addr < 0xC000){ + if (0){//ctrl_data_in->data.poke_args.addr < 0xC000){ printf("error! tried to poke into 0x%x\n", ctrl_data_in->data.poke_args.addr); } else switch(ctrl_data_in->data.poke_args.num_bytes){ diff --git a/firmware/microblaze/apps/uart_flash_loader.c b/firmware/microblaze/apps/uart_flash_loader.c new file mode 100644 index 000000000..d67b84677 --- /dev/null +++ b/firmware/microblaze/apps/uart_flash_loader.c @@ -0,0 +1,169 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +//#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + +//uses UART to load files to Flash in Intel HEX 16-bit format. +//this is one example of a "safe" firmware image to be loaded by a bootloader into main RAM. +//this CANNOT write to main RAM, since it is resident there. + +//Sector 0-31: Safe FPGA bootloader image +//Sector 32-63: Production bootloader image +//Sector 64: Production firmware image +//Sector 127: Safe firmware image + + +void uart_flash_loader(void) { + + char buf[256]; //input data buffer + uint8_t ihx[32]; //ihex data buffer + uint32_t slot_offset = PROD_FW_IMAGE_LOCATION_ADDR; //initial slot offset to program to. + uint32_t extended_addr = 0x00000000; //extended Intel hex segment address + + size_t sector_size = spi_flash_log2_sector_size(); + ihex_record_t ihex_record; + ihex_record.data = ihx; + int i; + + + //not gonna win a turing prize for my C text parsing + while(1) { + gets(buf); + if(!strncmp(buf, "!SECTORSIZE", 7)) { //return the sector size in log format + putstr("OK "); + puthex8((uint32_t) sector_size); //err, this should probably be decimal for human readability. we do have itoa now... + putstr("\n"); + } + else if(!strncmp(buf, "!SETADDR", 7)) { //set start address for programming + slot_offset = atol(&buf[8]); + puts("OK"); +// puthex32(slot_offset); +// putstr("\n"); + } + else if(!strncmp(buf, "!ERASE", 6)) { //erase a sector + uint32_t sector = atol(&buf[6]); + uint32_t size = 2 << (sector_size-1); + uint32_t addr = sector << sector_size; + + spi_flash_erase(addr, size); //we DO NOT implement write protection here. it is up to the HOST PROGRAM to not issue an ERASE unless it means it. + //unfortunately the Flash cannot write-protect the segments that really matter, so we only use global write-protect + //as a means of avoiding accidental writes from runaway code / garbage on the SPI bus. + puts("OK"); + } +//can't exactly run firmware if you're already executing out of main RAM +/* else if(!strncmp(buf, "!RUNSFW", 7)) { + if(is_valid_fw_image(SAFE_FW_IMAGE_LOCATION_ADDR)) { + puts("OK"); + spi_flash_read(SAFE_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE); + start_program(RAM_BASE); + } else { + puts("NOK"); + } + } + else if(!strncmp(buf, "!RUNPFW", 7)) { + if(is_valid_fw_image(PROD_FW_IMAGE_LOCATION_ADDR)) { + puts("OK"); + spi_flash_read(PROD_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES-1, (void *)RAM_BASE); + start_program(RAM_BASE); + } else { + puts("NOK"); + } + } +*/ + else if(!strncmp(buf, "!RUNPFPGA", 8)) { + if(is_valid_fpga_image(PROD_FPGA_IMAGE_LOCATION_ADDR)) { + puts("OK"); + //icap_reload_fpga(PROD_FPGA_IMAGE_LOCATION_ADDR); + } else { + puts("NOK"); + } + } + else if(!strncmp(buf, "!RUNSFPGA", 8)) { + if(is_valid_fpga_image(SAFE_FPGA_IMAGE_LOCATION_ADDR)) { + puts("OK"); + //icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + } else { + puts("NOK"); + } + } + else if(!strncmp(buf, "!READ", 5)) { + uint32_t addr = atol(&buf[5]); + spi_flash_read(addr, 16, ihx); + for(i=0; i < 16; i++) { + puthex8(ihx[i]); + } + putstr("\n"); + } + + else if(!ihex_parse(buf, &ihex_record)) { //last, try to see if the input was a valid IHEX line + switch (ihex_record.type) { + case 0: + spi_flash_program(ihex_record.addr + slot_offset + extended_addr, ihex_record.length, ihex_record.data); + puts("OK"); + break; + case 1: + //here we would expect a CRC checking or something else to take place. for now we do nothing. + //well, we set the extended segment addr back to 0 + extended_addr = 0; + puts("DONE"); + break; + case 4: + //set the upper 16 bits of the address + extended_addr = ((ihex_record.data[0] << 8) + ihex_record.data[1]) << 16; + puts("OK"); + break; + default: + puts("NOK"); + } + } + else puts("NOK"); + } //while(1) +} + +void delay(uint32_t t) { + while(t-- != 0) asm("NOP"); +} + +int main(int argc, char *argv[]) { + uint8_t buf[32]; + int i = 0; + + hal_disable_ints(); // In case we got here via jmp 0x0 + +// delay(10000000); + + //before anything else you might want to blinkenlights just to indicate code startup to the user. + + hal_uart_init(); + spif_init(); +// i2c_init(); //for EEPROM + puts("USRP2+ UART firmware loader"); + +// puts("Debug: loading production image, 10 bytes."); + +// spi_flash_read(PROD_FW_IMAGE_LOCATION_ADDR, 10, buf); +// for(i=0; i < 10; i++) { +// puthex8(buf[i]); +// } + + uart_flash_loader(); + + //shouldn't get here. should reboot. + puts("shit happened.\n"); + + return 0; +} diff --git a/firmware/microblaze/bin/bin_to_mif.py b/firmware/microblaze/bin/bin_to_mif.py new file mode 100755 index 000000000..cefce4e92 --- /dev/null +++ b/firmware/microblaze/bin/bin_to_mif.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +import struct +import sys + +hextab = ('0000', '0001', '0010', '0011', + '0100', '0101', '0110', '0111', + '1000', '1001', '1010', '1011', + '1100', '1101', '1110', '1111') + +def w_to_binary_ascii(w): + return ''.join([hextab[(w >> 4*i) & 0xf] for i in range(7,-1,-1)]) + +def bin_to_mif(bin_input_file, mif_output_file): + ifile = open(bin_input_file, 'rb') + ofile = open(mif_output_file, 'w') + idata = ifile.read() + fmt = ">%dI" % ((len(idata) / 4),) + words = struct.unpack(fmt, idata) + for w in words: + ofile.write(w_to_binary_ascii(w)) + ofile.write('\n') + +if __name__ == '__main__': + if len(sys.argv) != 3: + sys.stderr.write("usage: bin_to_mif bin_input_file mif_output_file\n") + raise SystemExit, 1 + + bin_to_mif(sys.argv[1], sys.argv[2]) diff --git a/firmware/microblaze/bin/bin_to_ram_macro_init.py b/firmware/microblaze/bin/bin_to_ram_macro_init.py new file mode 100755 index 000000000..65cf2dbdf --- /dev/null +++ b/firmware/microblaze/bin/bin_to_ram_macro_init.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +import struct +import sys + +def do_8_words(ofile, which_ram, row, words): + ofile.write("defparam bootram.RAM%d.INIT_%02X=256'h" % (which_ram, row)) + ofile.write("%08x_%08x_%08x_%08x_%08x_%08x_%08x_%08x;\n" % ( + words[7], words[6], words[5], words[4], words[3], words[2], words[1], words[0])) + +def bin_to_ram_macro_init(bin_input_file, ram_init_output_file): + ifile = open(bin_input_file, 'rb') + ofile = open(ram_init_output_file, 'w') + idata = ifile.read() + fmt = ">%dI" % ((len(idata) / 4),) + words = struct.unpack(fmt, idata) + + # pad to a multiple of 8 words + r = len(words) % 8 + if r != 0: + words += (8 - r) * (0,) + + if len(words) > 2048: + sys.stderr.write("bin_to_macro_init: error: input file %s is > 8KiB\n" % (bin_input_file,)) + sys.exit(1) + + # first 2KB + for i in range(0, min(512, len(words)), 8): + do_8_words(ofile, 0, i/8, words[i:i+8]) + + # second 2KB + for i in range(512, min(1024, len(words)), 8): + do_8_words(ofile, 1, (i/8) % 64, words[i:i+8]) + + # third 2KB + for i in range(1024, min(1536, len(words)), 8): + do_8_words(ofile, 2, (i/8) % 64, words[i:i+8]) + + # last 2KB + for i in range(1536, len(words), 8): + do_8_words(ofile, 3, (i/8) % 64, words[i:i+8]) + +if __name__ == '__main__': + if len(sys.argv) != 3: + sys.stderr.write("usage: bin_to_ram_macro_init bin_input_file ram_init_output_file\n") + sys.exit(1) + + bin_to_ram_macro_init(sys.argv[1], sys.argv[2]) diff --git a/firmware/microblaze/bin/elf_to_sbf b/firmware/microblaze/bin/elf_to_sbf new file mode 100755 index 000000000..d1be10c0d --- /dev/null +++ b/firmware/microblaze/bin/elf_to_sbf @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, see . +# + +import sys +import struct +from optparse import OptionParser +from pprint import pprint + +import sbf + +# see /usr/include/elf.h for the various magic values + + +_ehdr_fmt = ">16sHH5I6H" +_ehdr_fmt_size = struct.calcsize(_ehdr_fmt) +_phdr_fmt = ">8I" +_phdr_fmt_size = struct.calcsize(_phdr_fmt) + +class elf32_ehdr(object): + def __init__(self, s): + (self.ident, self.type, self.machine, self.version, self.entry, + self.phoff, self.shoff, self.flags, self.ehsize, + self.phentsize, self.phnum, self.shentsize, self.shnum, + self.shstrndx) = struct.unpack(_ehdr_fmt, s) + +class elf32_phdr(object): + def __init__(self, s): + (self.type, self.offset, self.vaddr, self.paddr, + self.filesz, self.memsz, + self.flags, self.align) = struct.unpack(_phdr_fmt, s) + + def __repr__(self): + return "" % ( + p_type_str(self.type), self.offset, self.paddr, self.filesz) + + +def p_type_str(t): + if t <= 8: + return ('NULL', 'LOAD', 'DYNAMIC', 'INTERP', 'NOTE', 'SHLIB', 'PHDR', 'TLS', 'NUM')[t] + return "0x%x" % (t,) + + + +def _get_ehdr(f): + if len(f) < _ehdr_fmt_size: + return False + ehdr = elf32_ehdr(f[0:_ehdr_fmt_size]) + return ehdr + + +def elf32_big_endian_exec_p(f): + ehdr = _get_ehdr(f) + if not ehdr: + return False + + #pprint(ehdr, sys.stderr) + e_ident = ehdr.ident + if not e_ident.startswith('\177ELF'): + return False + if (ord(e_ident[4]) != 1 # EI_CLASS == CLASS32 + or ord(e_ident[5]) != 2 # EI_DATA == DATA2MSB + or ord(e_ident[6]) != 1 # EI_VERSION == EV_CURRENT + ): + return False + + if ehdr.type != 2: # e_type == ET_EXEC + return False + + return True + + + +# return (entry, (phdr, ...)) + +def get_elf32_prog_headers(f): + ehdr = _get_ehdr(f) + entry = ehdr.entry + phoff = ehdr.phoff + phentsize = ehdr.phentsize + phnum = ehdr.phnum + + def extract(i): + start = phoff + i * phentsize + end = start + phentsize + return f[start:end] + + return (entry, [elf32_phdr(extract(i)) for i in range(phnum)]) + + +def main(): + usage = "%prog: [options] elf_file" + parser = OptionParser() + parser.add_option("-o", "--output", default=None, + help="specify output filename [default=stdout]") + (options, args) = parser.parse_args() + if len(args) != 1: + parser.print_help() + sys.exit(1) + + elf_file = open(args[0], 'rb') + + elf_contents = elf_file.read() + if not elf32_big_endian_exec_p(elf_contents): + sys.stderr.write("%s: not a big-endian 32-bit ELF executable\n" % (args[0],)) + sys.exit(1) + + if options.output is None: + sbf_file = sys.stdout + else: + sbf_file = open(options.output, 'wb') + + (entry, phdrs) = get_elf32_prog_headers(elf_contents) + #pprint(phdrs, sys.stderr) + + def phdr_to_sec_desc(phdr): + target_addr = phdr.paddr + data = elf_contents[phdr.offset:phdr.offset+phdr.filesz] + #print >>sys.stderr, "pdhr_to_sec_desc:", (target_addr, data) + return sbf.sec_desc(target_addr, data) + + sections = map(phdr_to_sec_desc, phdrs) + # pprint(sections, sys.stderr) + sbf.write_sbf(sbf_file, sbf.header(entry, sections)) + + +if __name__ == '__main__': + main() diff --git a/firmware/microblaze/bin/sbf.py b/firmware/microblaze/bin/sbf.py new file mode 100644 index 000000000..8e2c868a5 --- /dev/null +++ b/firmware/microblaze/bin/sbf.py @@ -0,0 +1,134 @@ +# +# Copyright 2009 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, see . +# + +_SBF_MAGIC = 'SBF!' +_SBF_DONT_EXECUTE = 0x1 +_SBF_MAX_SECTIONS = 14 +_SBF_HEADER_LEN = 128 + +import struct +import sys +from pprint import pprint + +def dump_data(f, offset, data): + L = len(data) // 4 + for i in range(L): + f.write('%08x: %08x\n' % (offset + 4 * i, struct.unpack('>I', data[4*i:4*(i+1)])[0])) + remainder = len(data) - L * 4 + if remainder != 0: + f.write('%08x: ' % (offset + L*4,)) + i = 0 + while i < remainder: + f.write('%02x' % ((ord(data[L*4 + i]),))) + i += 1 + f.write('\n') + + + +class sec_desc(object): + def __init__(self, target_addr, data): + self.target_addr = target_addr + self.data = data + + def __repr__(self): + #print >>sys.stderr, "target_addr:", self.target_addr + #print >>sys.stderr, "data:", self.data + return "" % ( + self.target_addr, len(self.data)) + + +class header(object): + def __init__(self, entry, sections): + self.entry = entry + self.section = sections + + def dump(self, f): + if self.entry == _SBF_DONT_EXECUTE: + f.write("Entry: DONT_EXECUTE\n") + else: + f.write("Entry: 0x%x\n" % (self.entry,)) + for i in range(len(self.section)): + s = self.section[i] + f.write("Section[%d]: target_addr = 0x%x length = %d\n" % (i, + s.target_addr, + len(s.data))) + dump_data(f, s.target_addr, s.data) + + # + # Returns an iterator. Each yield returns (target_addr, data) + # + def iterator(self, max_piece=512): + for s in self.section: + offset = 0 + L = len(s.data) + while offset < L: + n = min(max_piece, L - offset) + yield (s.target_addr + offset, + s.data[offset:offset+n]) + offset += n + + + +def read_sbf(input_file): + """Parse an SBF file""" + + f = input_file.read(_SBF_HEADER_LEN) + #if len(f) < _SBF_HEADER_LEN or not f.startswith(_SBF_MAGIC): + #raise ValueError, '%s: not an SBF file' % (input_file.name,) + + def extract(i): + start = 16+8*i + stop = start+8 + return struct.unpack('>2I', f[start:stop]) + + def get_data(ss): + L = ss[1] + s = input_file.read(L) + #if len(s) != L: + #raise ValueError, '%s: file is too short' % (input_file.name(),) + return s + + (magic, entry, nsections, reserved) = struct.unpack('>4s3I', f[0:16]) + assert nsections <= _SBF_MAX_SECTIONS + descs = [extract(i) for i in range(nsections)] + #pprint(descs, sys.stderr) + data = map(get_data, descs) + secs = map(lambda ss, data: sec_desc(ss[0], data), descs, data) + return header(entry, secs) + + +def write_sbf(output_file, sbf_header): + assert(len(sbf_header.section) <= _SBF_MAX_SECTIONS) + sbf_header.nsections = len(sbf_header.section) + f = output_file + + # write the file header + f.write(struct.pack('>4s3I', _SBF_MAGIC, sbf_header.entry, sbf_header.nsections, 0)) + + # write the section headers + for i in range(sbf_header.nsections): + f.write(struct.pack('>2I', + sbf_header.section[i].target_addr, + len(sbf_header.section[i].data))) + for i in range(_SBF_MAX_SECTIONS - sbf_header.nsections): + f.write(struct.pack('>2I', 0, 0)) + + # write the section data + for i in range(sbf_header.nsections): + f.write(sbf_header.section[i].data) + + return True diff --git a/firmware/microblaze/bin/serial_loader b/firmware/microblaze/bin/serial_loader new file mode 100755 index 000000000..9bd5aada7 --- /dev/null +++ b/firmware/microblaze/bin/serial_loader @@ -0,0 +1,363 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, see . +# + +import termios +import tty +import os +import sys +import threading +import Queue +from optparse import OptionParser +import time + +import sbf + +GDB_ESCAPE = chr(0x7d) + +# Indexes for termios list. +IFLAG = 0 +OFLAG = 1 +CFLAG = 2 +LFLAG = 3 +ISPEED = 4 +OSPEED = 5 +CC = 6 + +class terminal(object): + def __init__(self, device, speed_bits): + fd = os.open(device, os.O_RDWR) + if not os.isatty(fd): + raise ValueError(device + " is not a tty") + + self.read_file = os.fdopen(fd, "rb", 0) + self.write_file = os.fdopen(os.dup(fd), "wb", 0) + self.old_attrs = termios.tcgetattr(self.write_file.fileno()) + #print "old_attrs: ", self.old_attrs + attrs = list(self.old_attrs) # copy of attributes + attrs[ISPEED] = speed_bits # set input and output speed + attrs[OSPEED] = speed_bits + termios.tcsetattr(self.write_file.fileno(), termios.TCSAFLUSH, attrs) + tty.setraw(self.write_file.fileno()) # enable raw mode + attrs = termios.tcgetattr(self.write_file.fileno()) + attrs[CC][termios.VMIN] = 1 # minimim of 1 char + attrs[CC][termios.VTIME] = 1 # wait no longer than 1/10 + termios.tcsetattr(self.write_file.fileno(), termios.TCSAFLUSH, attrs) + + def __del__(self): + termios.tcsetattr(self.write_file.fileno(), termios.TCSAFLUSH, self.old_attrs) + self.read_file.close() + self.write_file.close() + + def read(self, n): + """Read at most n bytes from tty""" + return self.read_file.read(n) + + def write(self, str): + """Write str to tty.""" + return self.write_file.write(str) + + +def hexnibble(i): + return "0123456789abcdef"[i & 0xf] + +def build_pkt(payload): + s = ['$'] + checksum = 0 + + for p in payload: + if p in ('$', '#', GDB_ESCAPE): + s.append(GDB_ESCAPE) + s.append(p) + checksum += ord(p) + + checksum &= 0xff + s.append('#') + s.append(hexnibble(checksum >> 4)) + s.append(hexnibble(checksum)) + + return ''.join(s) + + +def build_memory_read_pkt(addr, len): + return build_pkt(('m%x,%x' % (addr, len))) + +def build_memory_write_hex_pkt(addr, s): + hexdata = ''.join(["%02x" % (ord(c),) for c in s]) + return build_pkt(('M%x,%x:' % (addr, len(s))) + hexdata) + +def build_memory_write_pkt(addr, s): + return build_pkt(('X%x,%x:' % (addr, len(s))) + s) + +def build_goto_pkt(addr): + return build_pkt(('c%x' % (addr,))) + + +def get_packet(f): + """Return a valid packet, or None on EOF or timeout""" + LOOKING_FOR_DOLLAR = 0 + LOOKING_FOR_HASH = 1 + CSUM1 = 2 + CSUM2 = 3 + + fd = f.fileno() + + state = LOOKING_FOR_DOLLAR + buf = [] + + while True: + ch = os.read(fd, 1) + sys.stdout.write(ch) + if len(ch) == 0: + print("Returning None") + return(None) + + if state == LOOKING_FOR_DOLLAR: + if ch == '$': + buf = [] + state = LOOKING_FOR_HASH + elif ch == '#': + state = LOOKING_FOR_DOLLAR + + elif state == LOOKING_FOR_HASH: + if ch == '$': + state = LOOKING_FOR_DOLLAR + elif ch == '#': + state = CSUM1 + else: + if ch == GDB_ESCAPE: + ch = getc() + buf.append(ch) + + elif state == CSUM1: + chksum1 = ch + state = CSUM2 + + elif state == CSUM2: + chksum2 = ch + r = ''.join(buf) + if chksum1 == '.' and chksum2 == '.': + return r + + expected_checksum = int(chksum1 + chksum2, 16) + checksum = 0 + for c in buf: + checksum += ord(c) + + checksum &= 0xff + if checksum == expected_checksum: + return r + + state = LOOKING_FOR_DOLLAR + + else: + raise ValueError( "Invalid state") + + +class packet_reader_thread(threading.Thread): + def __init__(self, tty_in, q): + threading.Thread.__init__(self) + self.setDaemon(1) + self.tty_in = tty_in + self.q = q + self._keep_running = True + self.start() + + def run(self): + while self._keep_running == True: + p = get_packet(self.tty_in) + if p is not None: + self.q.put(('pkt', p)) + + +def _make_tr_table(): + table = [] + for c in range(256): + if c < ord(' ') or c > ord('~'): + table.append('.') + else: + table.append(chr(c)) + return ''.join(table) + + +class controller(object): + def __init__(self, tty): + self.tty = tty + self.q = Queue.Queue(0) + self.timers = {} + self.next_tid = 1 + self.current_tid = 0 + self.ntimeouts = 0 + self.packet_reader = packet_reader_thread(tty.read_file, self.q) + self.state = None + self.debug = False + self.tt = _make_tr_table() + + self.done = False + self.addr = None + self.bits = None + + def shutdown(self): + self.packet_reader._keep_running = False + + def start_timeout(self, timeout_in_secs): + def callback(tid): + if self.timers.has_key(tid): + del self.timers[tid] + self.q.put(('timeout', tid)) + self.next_tid += 1 + tid = self.next_tid + timer = threading.Timer(timeout_in_secs, callback, (tid,)) + self.timers[tid] = timer + timer.start() + return tid + + def cancel_timeout(self, tid): + if self.timers.has_key(tid): + self.timers[tid].cancel() + del self.timers[tid] + + def send_packet(self, pkt): + if self.debug: + if len(pkt) > 64: + s = pkt[0:64] + '...' + else: + s = pkt + sys.stdout.write('-> ' + s.translate(self.tt) + '\n') + self.tty.write(pkt); + + def send_packet_start_timeout(self, pkt, secs): + self.send_packet(pkt) + self.current_tid = self.start_timeout(secs) + + def upload_code(self, sbf): + MAX_PIECE = 512 # biggest piece to send + MWRITE_TIMEOUT = 0.1 + + IDLE = 0 + WAIT_FOR_ACK = 1 + UPLOAD_DONE = 2 + DONE = 3 + FAILED = 4 + + self.done = False + it = sbf.iterator(MAX_PIECE) + entry_addr = sbf.entry + + def get_next_bits(): + try: + (self.addr, self.bits) = it.next() + except StopIteration: + self.done = True + + def is_done(): + return self.done + + def send_piece(): + pkt = build_memory_write_pkt(self.addr, self.bits) + #pkt = build_memory_write_hex_pkt(self.addr, self.bits) + self.send_packet_start_timeout(pkt, MWRITE_TIMEOUT) + state = WAIT_FOR_ACK + + def advance(): + get_next_bits() + if is_done(): + self.state = DONE + self.send_packet(build_goto_pkt(entry_addr)) + + else: + self.ntimeouts = 0 + send_piece() + + get_next_bits() + if is_done(): # empty file + return True + + send_piece() # initial transition + + while 1: + (event, value) = self.q.get() + + if event == 'timeout' and value == self.current_tid: + self.ntimeouts += 1 + if self.ntimeouts >= 5: + return False # say we failed + send_piece() # resend + + + elif event == 'pkt': + if value == 'OK': + self.cancel_timeout(self.current_tid) + advance() + if self.state == DONE: + return True + else: + print("Error returned from firmware: " + value) + return False + + else: + print("Unknown event:", (event, value)) + +def main(): + usage="%prog: [options] filename" + parser = OptionParser(usage=usage) + parser.add_option("-t", "--tty", type="string", default="/dev/ttyS0", + help="select serial port [default=%default]") + + (options, args) = parser.parse_args() + if len(args) != 1: + parser.print_help() + raise SystemExit(1) + + + filename = args[0] + f = open(filename, "rb") + try: + # Try to open the file as an SBF file + sbf_header = sbf.read_sbf(f) + except: + # If that fails, build an SBF from the binary, assuming default + # load address and entry point + f.seek(0) + t = f.read() + if t.startswith('\177ELF'): + sys.stderr.write("Can't load an ELF file. Please use an SBF file instead.\n") + raise SystemExit( 1) + sbf_header = sbf.header(0x8000, [sbf.sec_desc(0x8000, t)]) + + + tty = terminal(options.tty, termios.B115200) + ctrl = controller(tty) + ok = ctrl.upload_code(sbf_header) + + if ok: + print("OK") + try: + raw_input("Press Enter to exit: ") + except KeyboardInterrupt: + pass + ctrl.shutdown() + time.sleep(0.2) + + else: + print("Upload failed") + ctrl.shutdown() + + + +if __name__ == "__main__": + main() diff --git a/firmware/microblaze/bin/uart_ihex_flash_loader.py b/firmware/microblaze/bin/uart_ihex_flash_loader.py new file mode 100755 index 000000000..5a3300f34 --- /dev/null +++ b/firmware/microblaze/bin/uart_ihex_flash_loader.py @@ -0,0 +1,138 @@ +#!/usr/bin/python + +import serial +from optparse import OptionParser +import os, sys + +#TODO: pull everything but parser out of main() and put it in a separate function we can call from another script. lets us automate loading RAM+FLASH to produce a fully-loaded image. +#TODO: make it fail gracefully -- if it gets a NOK or times out, do at least one retry. +#TODO: put hooks in (eventually) to allow verifying a firmware image so the user can more safely update the "safe" image +#TODO: how about a progress indicator? FPGA images take FOREVER. you can use wc -l to get the number of lines, or do it with file i/o. + +def main(): + usage="%prog: [options] filename" + parser = OptionParser(usage=usage) + parser.add_option("-t", "--tty", type="string", default="/dev/ttyUSB0", + help="select serial port [default=%default]") + parser.add_option("-b", "--baudrate", type=int, default=115200, + help="set baudrate [default=%default]") + parser.add_option("-F", "--write-safe-firmware", action="store_const", const=1, dest="image", + help="write to safe firmware image") + parser.add_option("-f", "--write-production-firmware", action="store_const", const=2, dest="image", + help="write to production firmware image") + parser.add_option("-P", "--write-safe-fpga", action="store_const", const=3, dest="image", + help="write to safe FPGA image") + parser.add_option("-p", "--write-production-fpga", action="store_const", const=4, dest="image", + help="write to production FPGA image") + + (options, args) = parser.parse_args() + + if(options.image is None): + print("At least one of -f, -F, -p, -P must be specified.\n") + parser.print_help() + raise SystemExit(1) + + if len(args) != 1: + parser.print_help() + raise SystemExit(1) + + if(options.image == 3): + print "Are you *really* sure you want to write to the failsafe FPGA image? If you mess this up your USRP2+ will become a brick. Press 'y' to continue, any other key to abort." + if(raw_input().rstrip() is not "y"): + print "Good choice." + raise SystemExit(0) + + elif(options.image == 1): + print "Are you *really* sure you want to write to the failsafe firmware image? If you mess this up your USRP2+ will only be able to be reprogrammed via the UART RAM loader.\nPress 'y' to continue, any other key to abort." + if(raw_input().rstrip() is not "y"): + print "Good choice." + raise SystemExit(0) + + filename = args[0] + f = open(filename, "r") + + #now we start doing things... + if(os.path.exists(options.tty) is False): + sys.stderr.write("No serial port found at %s\n" % options.tty) + raise SystemExit(1) + + try: + ser = serial.Serial(port=options.tty, timeout=1, baudrate=options.baudrate, bytesize=8, parity=serial.PARITY_NONE, stopbits=1, rtscts=0, xonxoff=0) + except serial.SerialException: + sys.stderr.write("Unable to open serial port\n") + raise SystemExit(1) + + ser.open() + +#test to see if a valid USRP2+ in flash load mode is connected + ser.write("garbage\n") + ser.readline() + ser.write("!SECTORSIZE\n") + reply = ser.readline().rstrip() + if("NOK" in reply): + sys.stderr.write("Error writing to USRP2+. Try again.\n") + raise SystemExit(1) + elif("OK" in reply): + sectorsize = int(reply[3:5], 16) + print("USRP2+ found with sector size %i. Erasing old image." % 2**sectorsize) + else: + sys.stderr.write("Invalid response or no USRP2+ connected.\n") + raise SystemExit(1) + + if(options.image == 1): + sectors = range(127, 128) + runcmd = "!RUNSFD\n" + elif(options.image == 2): + sectors = range(64, 65) + runcmd = "!RUNPFD\n" + elif(options.image == 3): + sectors = range(0,32) + runcmd = "!RUNSFPGA\n" + elif(options.image == 4): + sectors = range(32,64) + runcmd = "!RUNPFPGA\n" + + writeaddr = sectors[0] << sectorsize + if(options.image < 3): + writeaddr -= 0x8000 #i know this is awkward, but we subtract 0x8000 from the address for firmware loads. the reason we do this is that the IHX files are located at 0x8000 (RAM_BASE), and + #doing this here allows us to use the same IHX files for RAM load as for Flash load, without relocating in objcopy or relinking with another ld script. + #this limits us to writing above 32K for our firmware images. since the safe FPGA image located at 0x00000000 takes up 2MB of space this isn't really a worry. + #FPGA images (.mcs) always start at 0x00000000 so they don't need this relocation. + + for sector in sectors: + print "Erasing sector %i" % sector + ser.write("!ERASE %i\n" % sector) + reply = ser.readline() + if("NOK" in reply): + sys.stderr.write("Error erasing sector %i" % sector) + raise SystemExit(1) + + print "Setting start address to %i" % writeaddr + ser.write("!SETADDR %i\n" % writeaddr) + if("NOK" in reply): + sys.stderr.write("Error setting address\n") + raise SystemExit(1) + else: + print reply + + + for line in f: + ser.write(line.rstrip()+'\n') + reply = ser.readline() + if("NOK" in reply): #TODO: simplify this logic, use (reply.rstrip() is "NOK") + print("Received NOK reply during data write") + raise SystemExit(1) + elif("DONE" in reply): + print("Finished writing program. Loading...\n") + ser.write(runcmd) + elif("OK" not in reply): + print("Received invalid reply %s during data write" % reply) + raise SystemExit(1) + else: + print reply.rstrip() + '\t' + line.rstrip() + + print ser.readline() + + +if __name__ == '__main__': + main() diff --git a/firmware/microblaze/bin/uart_ihex_ram_loader.py b/firmware/microblaze/bin/uart_ihex_ram_loader.py new file mode 100755 index 000000000..c90fbe1d8 --- /dev/null +++ b/firmware/microblaze/bin/uart_ihex_ram_loader.py @@ -0,0 +1,70 @@ +#!/usr/bin/python + +import serial +from optparse import OptionParser +import os, sys + +def main(): + usage="%prog: [options] filename" + parser = OptionParser(usage=usage) + parser.add_option("-t", "--tty", type="string", default="/dev/ttyUSB0", + help="select serial port [default=%default]") + parser.add_option("-b", "--baudrate", type=int, default=115200, + help="set baudrate [default=%default]") + + (options, args) = parser.parse_args() + if len(args) != 1: + parser.print_help() + raise SystemExit(1) + + filename = args[0] + f = open(filename, "r") + + #all we have to do is load the IHX file and attempt to spit it out to the serial port. + if(os.path.exists(options.tty) is False): + sys.stderr.write("No serial port found at %s\n" % options.tty) + raise SystemExit(1) + + try: + ser = serial.Serial(port=options.tty, timeout=1, baudrate=options.baudrate, bytesize=8, parity=serial.PARITY_NONE, stopbits=1, rtscts=0, xonxoff=0) + except serial.SerialException: + sys.stderr.write("Unable to open serial port\n") + raise SystemExit(1) + + ser.open() + +#test to see if a valid USRP2+ in RAM load mode is connected + + ser.write("WOOOOO\n"); + reply = ser.readline() + if("NOK" not in reply): + sys.stderr.write("Valid USRP2+ not connected or no response received\n") + raise SystemExit(1) + else: + print("USRP2+ found.") + + for line in f: + ser.write(line.rstrip() + '\n') + reply = ser.readline() + if("NOK" in reply): #blocks to wait for response + print("Received NOK reply from USRP2+") + raise SystemExit(1) + elif("OK" not in reply): + print("Received invalid reply!") + raise SystemExit(1) +# else: +# print("OK received") + + print "USRP2+ RAM programmed.\nLoading program." + + #at this point it should have sent the end line of the file, which starts the program! + #we'll just act like a dumb terminal now +# ser.timeout = 0 +# try: +# while 1: +# print ser.readline() +# except KeyboardInterrupt: +# raise SystemExit(0) + +if __name__ == '__main__': + main() diff --git a/firmware/microblaze/bootstrap b/firmware/microblaze/bootstrap index 2343025cc..26987b0ec 100755 --- a/firmware/microblaze/bootstrap +++ b/firmware/microblaze/bootstrap @@ -17,6 +17,8 @@ # rm -rf *.cache +rm -rf libusrp2/.deps +rm -rf libusrp2p/.deps aclocal autoconf diff --git a/firmware/microblaze/configure.ac b/firmware/microblaze/configure.ac index 46968b7fb..f6986f2dd 100644 --- a/firmware/microblaze/configure.ac +++ b/firmware/microblaze/configure.ac @@ -32,6 +32,7 @@ m4_if(m4_defn([m4_PACKAGE_VERSION]), [2.64], [m4_define([_AC_LANG_IO_PROGRAM(]_GCC_LANG[)], m4_defn([AC_LANG_PROGRAM(]_GCC_LANG[)]))])]) AC_PROG_CC([mb-gcc]) +AM_PROG_CC_C_O LT_INIT ################################################## @@ -46,9 +47,8 @@ AC_PATH_PROG([HEXDUMP], [hexdump]) ################################################## AC_CONFIG_FILES([ \ Makefile \ - apps/Makefile \ - include/Makefile \ - include/net/Makefile \ - lib/Makefile \ + usrp2p/bootloader/Makefile \ + usrp2/Makefile \ + usrp2p/Makefile \ ]) AC_OUTPUT diff --git a/firmware/microblaze/lib/Makefile.inc b/firmware/microblaze/lib/Makefile.inc new file mode 100644 index 000000000..0e88298b8 --- /dev/null +++ b/firmware/microblaze/lib/Makefile.inc @@ -0,0 +1,48 @@ +# +# Copyright 2010 Ettus Research LLC +# +# Copyright 2007 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, see . +# + +COMMON_SRCS = \ + $(top_srcdir)/lib/u2_init.c \ + $(top_srcdir)/lib/abort.c \ + $(top_srcdir)/lib/ad9510.c \ + $(top_srcdir)/lib/bsm12.c \ + $(top_srcdir)/lib/buffer_pool.c \ + $(top_srcdir)/lib/dbsm.c \ + $(top_srcdir)/lib/eeprom.c \ + $(top_srcdir)/lib/ethernet.c \ + $(top_srcdir)/lib/eth_mac.c \ + $(top_srcdir)/lib/_exit.c \ + $(top_srcdir)/lib/exit.c \ + $(top_srcdir)/lib/hal_io.c \ + $(top_srcdir)/lib/hal_uart.c \ + $(top_srcdir)/lib/i2c.c \ + $(top_srcdir)/lib/mdelay.c \ + $(top_srcdir)/lib/memcpy_wa.c \ + $(top_srcdir)/lib/memset_wa.c \ + $(top_srcdir)/lib/nonstdio.c \ + $(top_srcdir)/lib/pic.c \ + $(top_srcdir)/lib/print_mac_addr.c \ + $(top_srcdir)/lib/print_rmon_regs.c \ + $(top_srcdir)/lib/print_buffer.c \ + $(top_srcdir)/lib/printf.c \ + $(top_srcdir)/lib/ihex.c \ + $(top_srcdir)/lib/spi.c \ + $(top_srcdir)/lib/net_common.c \ + $(top_srcdir)/lib/arp_cache.c \ + $(top_srcdir)/lib/banal.c diff --git a/firmware/microblaze/lib/bootconfig.c b/firmware/microblaze/lib/bootconfig.c new file mode 100644 index 000000000..93adc05c2 --- /dev/null +++ b/firmware/microblaze/lib/bootconfig.c @@ -0,0 +1,101 @@ +/* -*- c -*- */ +/* + * Copyright 2009 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 . + */ +#ifdef HAVE_CONFIG_H +#include +#endif +#include "bootconfig.h" +#include "bootconfig_private.h" +#include +#include +#include +#include +#include +#include +#include + +eeprom_boot_info_t eeprom_shadow; + +static eeprom_boot_info_t eeprom_default = { + .magic = EEPROM_BOOT_INFO_MAGIC, + .nattempts = 1, + .next_boot.fpga_image_number = 0, + .next_boot.firmware_image_number = 0, + .default_boot.fpga_image_number = 0, + .default_boot.firmware_image_number = 0 +}; + +eeprom_boot_info_t * +_bc_get_eeprom_shadow(void) +{ + return &eeprom_shadow; +} + + +bool +_bc_write_eeprom_shadow(void) +{ + return eeprom_write(I2C_ADDR_MBOARD, BOOT_INFO_OFFSET, &eeprom_shadow, sizeof(eeprom_shadow)); +} + +void +bootconfig_init(void) +{ + if (!eeprom_read(I2C_ADDR_MBOARD, BOOT_INFO_OFFSET, &eeprom_shadow, sizeof(eeprom_shadow)) + || eeprom_shadow.magic != EEPROM_BOOT_INFO_MAGIC){ + eeprom_shadow = eeprom_default; + _bc_write_eeprom_shadow(); + } +} + +bootconfig_t +bootconfig_get_default(void) +{ + return eeprom_shadow.default_boot; +} + +bool +bootconfig_set_default(bootconfig_t bc) +{ + if (!validate_bootconfig(bc)) + return false; + + eeprom_shadow.default_boot = bc; + eeprom_shadow.next_boot = bc; + return _bc_write_eeprom_shadow(); +} + +void +bootconfig_boot(bootconfig_t bc) +{ + if (!validate_bootconfig(bc)) + return; + + eeprom_shadow.next_boot = bc; + eeprom_shadow.nattempts = 1; + _bc_write_eeprom_shadow(); + + if (1){ + puts("\nbootconfig: chaining to FPGA slot 0 bootloader"); + mdelay(100); + } + + while (1){ + // Reload fpga with code from SPI flash address 0x0. + icap_reload_fpga(0x00000000); + } +} diff --git a/firmware/microblaze/lib/clock_bits.h b/firmware/microblaze/lib/clock_bits.h new file mode 100644 index 000000000..d2052e941 --- /dev/null +++ b/firmware/microblaze/lib/clock_bits.h @@ -0,0 +1,55 @@ +// +// Copyright 2010 Ettus Research LLC +// +/* + * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_USRP2_CLOCK_BITS_H +#define INCLUDED_USRP2_CLOCK_BITS_H + +#define _MC_WE_LOCK 0x0001 +#define _MC_MIMO_CLK_INPUT 0x0002 // else SMA input + +/* + * Derived masks (use these): + * + * We get our input from 1 of three places: + * Our free running oscilator, our SMA connector, or from the MIMO connector + */ +#define MC_WE_DONT_LOCK 0x0000 +#define MC_WE_LOCK_TO_SMA (_MC_WE_LOCK | 0) +#define MC_WE_LOCK_TO_MIMO (_MC_WE_LOCK | _MC_MIMO_CLK_INPUT) + +/* + * Independent of the source of the clock, we may or may not drive our + * clock onto the mimo connector. Note that there are dedicated clock + * signals in each direction, so disaster doesn't occurs if we're + * unnecessarily providing clock. + */ +#define MC_PROVIDE_CLK_TO_MIMO 0x0004 + +#define MC_REF_CLK_MASK 0x0f + +#define MC_PPS_SOURCE_SMA (0x00 << 4) +#define MC_PPS_SOURCE_MIMO (0x01 << 4) + +#define MC_PPS_POLARITY_NEG (0x00 << 5) +#define MC_PPS_POLARITY_POS (0x01 << 5) + +#endif /* INCLUDED_USRP2_CLOCK_BITS_H */ diff --git a/firmware/microblaze/lib/clocks.h b/firmware/microblaze/lib/clocks.h index 43d5a05c2..a285e03dd 100644 --- a/firmware/microblaze/lib/clocks.h +++ b/firmware/microblaze/lib/clocks.h @@ -26,7 +26,7 @@ */ #include -#include +#include "clock_bits.h" /*! diff --git a/firmware/microblaze/lib/compiler.h b/firmware/microblaze/lib/compiler.h new file mode 100644 index 000000000..4fa9b49f8 --- /dev/null +++ b/firmware/microblaze/lib/compiler.h @@ -0,0 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 . + */ +#ifndef INCLUDED_COMPILER_H +#define INCLUDED_COMPILER_H + +// FIXME gcc specific. +#define _AL4 __attribute__((aligned (4))) + + +#endif /* INCLUDED_COMPILER_H */ diff --git a/firmware/microblaze/lib/ethernet.c b/firmware/microblaze/lib/ethernet.c index 34a3ad7c1..2d7c4d7bd 100644 --- a/firmware/microblaze/lib/ethernet.c +++ b/firmware/microblaze/lib/ethernet.c @@ -25,8 +25,7 @@ #include "nonstdio.h" #include #include "i2c.h" -#include "usrp2_i2c_addr.h" - +#include "usrp2/fw_common.h" #define VERBOSE 0 @@ -302,7 +301,7 @@ ethernet_mac_addr(void) return &src_mac_addr; eth_mac_addr_t tmp; - bool ok = eeprom_read(I2C_ADDR_MBOARD, MBOARD_MAC_ADDR, &tmp, sizeof(tmp)); + bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, &tmp, sizeof(tmp)); if (!ok || unprogrammed(&tmp, sizeof(tmp))){ // use the default } @@ -316,7 +315,7 @@ ethernet_mac_addr(void) bool ethernet_set_mac_addr(const eth_mac_addr_t *t) { - bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t)); + bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t)); if (ok){ src_mac_addr = *t; src_mac_addr_initialized = true; @@ -344,7 +343,7 @@ const struct ip_addr *get_ip_addr(void) return &src_ip_addr; struct ip_addr tmp; - bool ok = eeprom_read(I2C_ADDR_MBOARD, MBOARD_IP_ADDR, &tmp, sizeof(tmp)); + bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, &tmp, sizeof(tmp)); if (!ok || unprogrammed(&tmp, sizeof(tmp))){ // use the default } @@ -356,7 +355,7 @@ const struct ip_addr *get_ip_addr(void) } bool set_ip_addr(const struct ip_addr *t){ - bool ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_IP_ADDR, t, sizeof(struct ip_addr)); + bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, t, sizeof(struct ip_addr)); if (ok){ src_ip_addr = *t; src_ip_addr_initialized = true; diff --git a/firmware/microblaze/lib/gdbstub2.c b/firmware/microblaze/lib/gdbstub2.c new file mode 100644 index 000000000..4c63dfce2 --- /dev/null +++ b/firmware/microblaze/lib/gdbstub2.c @@ -0,0 +1,506 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 . + */ + +/* + * Implement a eensy weensy part of the GDB Remote Serial Protocol + * + * See Appendix D of the GDB manual + * + * m, -- read bytes of memory starting at + * Reply: + * XX... XX... is memory contents in hex + * ENN ENN NN is a hex error number + * + * M,:XX... -- write memory, data in hex + * Reply: + * OK for success + * ENN for an error. NN is a hex error number + * + * X,:XX... -- write memory, data in binary + * Reply: + * OK for success + * ENN for an error. NN is a hex error number + * + * c -- continue. is the address to resume (goto). + * Reply: + * + * \x80 New Format... + */ + +#include "gdbstub2.h" +#include "loader_parser.h" +#include "hal_uart.h" +#include +#include + +#define MAX_PACKET 1024 + +/* + * Get raw character from serial port, no echo. + */ +static inline int +gdb_getc(void) +{ + return hal_uart_getc(); +} + +/* + * Put character to serial port. Raw output. + */ +static inline void +gdb_putc(int ch) +{ + hal_uart_putc(ch); +} + +// ------------------------------------------------------------------------ + +#define GDB_ESCAPE 0x7d + +static unsigned char hex_table[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +static int +put_hex8_checksum(int ch, int checksum) +{ + unsigned char t = hex_table[(ch >> 4) & 0xf]; + checksum += t; + gdb_putc(t); + + t = hex_table[ch & 0xf]; + checksum += t; + gdb_putc(t); + return checksum; +} + +static void +put_hex8(int ch) +{ + put_hex8_checksum(ch, 0); +} + +static bool +hex4_to_bin(int ch, int *value) +{ + if ('0' <= ch && ch <= '9'){ + *value = ch - '0'; + return true; + } + if ('a' <= ch && ch <= 'f'){ + *value = ch - 'a' + 10; + return true; + } + if ('A' <= ch && ch <= 'F'){ + *value = ch - 'A' + 10; + return true; + } + *value = 0; + return false; +} + +static bool +hex8_to_bin(const unsigned char *s, int *value) +{ + int v0, v1; + if (hex4_to_bin(s[0], &v0) && hex4_to_bin(s[1], &v1)){ + *value = (v0 << 4) | v1; + return true; + } + return false; +} + +static bool +hex_to_bin_array(unsigned char *binary_data, const unsigned char *hex_data, size_t nbytes) +{ + for (size_t i = 0; i < nbytes; i++){ + int t; + if (!hex8_to_bin(&hex_data[2*i], &t)) + return false; + binary_data[i] = t; + } + return true; +} + +static bool +needs_escaping(int ch) +{ + return ch == '$' || ch == '#' || ch == GDB_ESCAPE; +} + +/* + * \brief Wait for a packet. + * \param[out] pkt_buf gets the received packet payload. + * \param[in] max_size is the maximum number of bytes to write into \p pkt_buf. + * \param[out] actual_size is the number of bytes written to \p pkt_buf. + * + * \returns true iff the payload fits and the checksum is OK. + * + * Packets have this format: + * + * $# + * + * Where is anything and is a two byte hex + * checksum. In '$', '#' and 0x7d are escaped with 0x7d. + * The checksum is computed as the modulo 256 sum of all characters + * btween the leading '$' and the trailing '#' (an 8-bit unsigned + * checksum). + */ +static bool +get_packet(unsigned char *pkt_buf, size_t max_size, size_t *actual_size) +{ + typedef enum states { + LOOKING_FOR_DOLLAR, + LOOKING_FOR_HASH, + CSUM1, + CSUM2, + } state_t; + + *actual_size = 0; + unsigned char csum[2] = {0, 0}; + state_t state = LOOKING_FOR_DOLLAR; + size_t pi = 0; + + while (1){ + int ch = gdb_getc(); + + switch (state){ + case LOOKING_FOR_DOLLAR: + if (ch == '$'){ + pi = 0; + state = LOOKING_FOR_HASH; + } + else if (ch == '#'){ // most likely missed the $ + return false; + } + break; + + case LOOKING_FOR_HASH: + if (ch == '$'){ + return false; + } + else if (ch == '#'){ + state = CSUM1; + } + else { + if (pi >= max_size) // payload too big + return false; + + if (ch == GDB_ESCAPE) + ch = gdb_getc(); + + pkt_buf[pi++] = ch; + } + break; + + case CSUM1: + csum[0] = ch; + state = CSUM2; + break; + + case CSUM2: + csum[1] = ch; + *actual_size = pi; + + // accept .. as a correct checksum + if (csum[0] == '.' && csum[1] == '.') + return true; + + int expected_checksum; + if (!hex8_to_bin(csum, &expected_checksum)) + return false; + + int checksum = 0; + for (size_t i = 0; i < pi; i++) + checksum += pkt_buf[i]; + + checksum &= 0xff; + return checksum == expected_checksum; + } + } +} + +static void +put_packet_trailer(int checksum) +{ + gdb_putc('#'); + put_hex8(checksum & 0xff); + gdb_putc('\r'); + gdb_putc('\n'); +} + +static void +put_packet(const unsigned char *pkt_buf, size_t size) +{ + gdb_putc('$'); + + int checksum = 0; + for (size_t i = 0; i < size; i++){ + int ch = pkt_buf[i]; + if (needs_escaping(ch)) + gdb_putc(GDB_ESCAPE); + gdb_putc(ch); + checksum += ch; + } + put_packet_trailer(checksum); +} + +/*! + * Read a hex number + * + * \param[inout] bufptr - pointer to pointer to buffer (updated on return) + * \param[in] end - one past end of valid data in buf + * \param[out] value - the parsed value + * + * \returns true iff a valid hex number was read from bufptr + */ +static bool +parse_number(const unsigned char **bufptr, const unsigned char *end, unsigned int *value) +{ + const unsigned char *buf = *bufptr; + unsigned int v = 0; + bool valid = false; + int nibble; + + while (buf < end && hex4_to_bin(*buf, &nibble)){ + valid = true; + v = (v << 4) | nibble; + buf++; + } + + *value = v; + *bufptr = buf; + return valid; +} + +static bool +parse_char(const unsigned char **bufptr, const unsigned char *end, unsigned char *ch) +{ + const unsigned char *buf = *bufptr; + if (buf < end){ + *ch = *buf++; + *bufptr = buf; + return true; + } + return false; +} + +static bool +expect_char(const unsigned char **bufptr, const unsigned char *end, unsigned char expected) +{ + unsigned char ch; + return parse_char(bufptr, end, &ch) && ch == expected; +} + +static bool +expect_end(const unsigned char **bufptr, const unsigned char *end) +{ + return *bufptr == end; +} + +static bool +parse_addr_length(const unsigned char **bufptr, const unsigned char *end, + unsigned int *addr, unsigned int *length) +{ + return (parse_number(bufptr, end, addr) + && expect_char(bufptr, end, ',') + && parse_number(bufptr, end, length)); +} + +static void +put_error(int error) +{ + unsigned char buf[3]; + buf[0] = 'E'; + buf[1] = hex_table[(error >> 4) & 0xf]; + buf[2] = hex_table[error & 0xf]; + + put_packet(buf, sizeof(buf)); +} + +static void +put_ok(void) +{ + const unsigned char buf[2] = "OK"; + put_packet(buf, sizeof(buf)); +} + +/* + * Read memory and send the reply. + * We do it on the fly so that our packet size is effectively unlimited + */ +static void +read_memory(unsigned int addr, unsigned int nbytes) +{ + int checksum = 0; + gdb_putc('$'); + + if ((addr & 0x3) == 0 && (nbytes & 0x3) == 0){ // word aligned + union { + unsigned int i; + unsigned char c[4]; + } u; + + unsigned int *p = (unsigned int *) addr; + unsigned int length = nbytes / 4; + + for (unsigned int i = 0; i < length; i++){ + u.i = p[i]; // do a word read + checksum = put_hex8_checksum(u.c[0], checksum); + checksum = put_hex8_checksum(u.c[1], checksum); + checksum = put_hex8_checksum(u.c[2], checksum); + checksum = put_hex8_checksum(u.c[3], checksum); + } + } + else { // byte aligned + unsigned char *p = (unsigned char *) addr; + for (unsigned int i = 0; i < nbytes; i++) + checksum = put_hex8_checksum(p[i], checksum); + } + + put_packet_trailer(checksum); +} + +static unsigned int +get_unaligned_int(const unsigned char *p) +{ + // we're bigendian + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); +} + +static bool +write_memory(unsigned int addr, size_t nbytes, + const unsigned char *data) +{ + if ((addr & 0x3) == 0 && (nbytes & 0x3) == 0){ // word-aligned dst + unsigned int *dst = (unsigned int *) addr; + size_t length = nbytes / 4; + for (size_t i = 0; i < length; i++){ + unsigned int t = get_unaligned_int(&data[4*i]); + dst[i] = t; // word writes + } + } + else { // non-word-aligned dst + unsigned char *dst = (unsigned char *) addr; + for (size_t i = 0; i < nbytes; i++){ + dst[i] = data[i]; + } + } + return true; +} + +void +gdbstub2_main_loop(void) +{ + unsigned char inpkt[MAX_PACKET + 24]; + unsigned char binary_data[MAX_PACKET/2] __attribute__((aligned (4))); + + hal_uart_set_mode(UART_MODE_RAW); //tell UART HAL not to map \n to \r\n + + while (1){ + size_t inpkt_len; + bool ok = get_packet(inpkt, sizeof(inpkt), &inpkt_len); + if (!ok){ + gdb_putc('-'); + continue; + } + gdb_putc('+'); + + const unsigned char *buf = inpkt; + const unsigned char *end = inpkt + inpkt_len; + unsigned char ch; + + if (!parse_char(&buf, end, &ch)){ // empty packet + put_packet(0, 0); + continue; + } + + unsigned int addr; + unsigned int length; + + switch(ch){ + case 'm': // m, -- read bytes starting at + if (!(parse_addr_length(&buf, end, &addr, &length) && expect_end(&buf, end))){ + put_error(1); + } + else { + read_memory(addr, length); + } + break; + + case 'M': // M,:XX... -- write bytes starting at + // XX... is the data in hex + if (!(parse_addr_length(&buf, end, &addr, &length) + && expect_char(&buf, end, ':') + && (end - buf) == 2 * length)){ + put_error(1); + } + else { + if (!hex_to_bin_array(binary_data, buf, length)) + put_error(2); + else if (!write_memory(addr, length, binary_data)) + put_error(3); + else + put_ok(); + } + break; + + case 'X': // X,:XX... -- write bytes starting at + // XX... is the data in binary + if (!(parse_addr_length(&buf, end, &addr, &length) + && expect_char(&buf, end, ':') + && (end - buf) == length)){ + put_error(1); + } + else { + if (!write_memory(addr, length, buf)) + put_error(3); + else + put_ok(); + } + break; + + case 'c': // c -- continue. is the address to resume (goto). + if (!(parse_number(&buf, end, &addr) + && expect_end(&buf, end))){ + put_error(1); + } + else { + typedef void (*fptr_t)(void); + (*(fptr_t) addr)(); // most likely no return + } + break; +/* + case 0x80: + { + unsigned char *output = binary_data; // reuse + size_t sizeof_output = sizeof(binary_data); + size_t actual_olen; + loader_parser(buf, end-buf, + output, sizeof_output, &actual_olen); + put_packet(output, actual_olen); + } + break; +*/ + default: // unknown packet type + put_packet(0, 0); + break; + } + } +} diff --git a/firmware/microblaze/lib/gdbstub2.h b/firmware/microblaze/lib/gdbstub2.h new file mode 100644 index 000000000..15cdde939 --- /dev/null +++ b/firmware/microblaze/lib/gdbstub2.h @@ -0,0 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 . + */ + +#ifndef INCLUDED_GDBSTUB_H +#define INCLUDED_GDBSTUB_H + +void gdbstub2_main_loop(void); + +#endif /* INCLUDED_GDBSTUB_H */ + diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index 0afd6a2cc..58b1e681e 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -193,3 +193,13 @@ puts(const char *s) putchar('\n'); return 0; } + +char * +gets(char * const s) +{ + char *x = s; + while((*x=(char)hal_uart_getc()) != '\n') x++; + *x = 0; + return s; +} + diff --git a/firmware/microblaze/lib/hal_io.h b/firmware/microblaze/lib/hal_io.h index d8967f063..c67d96c62 100644 --- a/firmware/microblaze/lib/hal_io.h +++ b/firmware/microblaze/lib/hal_io.h @@ -23,6 +23,7 @@ void hal_io_init(void); void hal_finish(); +char *gets(char * const s); /* * ------------------------------------------------------------------------ diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index 75b12b432..fe3b7515a 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -39,16 +39,25 @@ divisor_table[MAX_WB_DIV+1][NSPEEDS] = { #define u uart_regs +static char uart_mode = UART_MODE_ONLCR; + +void +hal_uart_set_mode(int mode) +{ + uart_mode = mode; +} + void hal_uart_init(void) { + hal_uart_set_mode(UART_MODE_ONLCR); u->clkdiv = 217; // 230400 bps } void hal_uart_putc(int ch) { - if (ch == '\n') // FIXME for now map \n -> \r\n + if (ch == '\n')// && (uart_mode == UART_MODE_ONLCR)) //map \n->\r\n if necessary hal_uart_putc('\r'); while (u->txlevel == 0) // wait for fifo to have space @@ -60,7 +69,7 @@ hal_uart_putc(int ch) void hal_uart_putc_nowait(int ch) { - if (ch == '\n') // FIXME for now map \n -> \r\n + if (ch == '\n')// && (uart_mode == UART_MODE_ONLCR)) //map \n->\r\n if necessary hal_uart_putc('\r'); if(u->txlevel) // If fifo has space diff --git a/firmware/microblaze/lib/hal_uart.h b/firmware/microblaze/lib/hal_uart.h index 2ddfa6259..dfd73c323 100644 --- a/firmware/microblaze/lib/hal_uart.h +++ b/firmware/microblaze/lib/hal_uart.h @@ -19,6 +19,16 @@ #ifndef INCLUDED_HAL_UART_H #define INCLUDED_HAL_UART_H +/*! + * \brief uart mode flags + */ +#define UART_MODE_RAW 0x0000 // no mapping on input or output +#define UART_MODE_ONLCR 0x0001 // map \n to \r\n on output (default) + +/* + * \brief Set uart mode + */ +void hal_uart_set_mode(int flags); /*! * \brief one-time call to init diff --git a/firmware/microblaze/lib/ihex.c b/firmware/microblaze/lib/ihex.c new file mode 100644 index 000000000..97ecf73b6 --- /dev/null +++ b/firmware/microblaze/lib/ihex.c @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +#include "ihex.h" +#include //man that pulls in a lot of shit + +//this is not safe and you should run isxdigit beforehand +uint8_t asc2nibble(char input) { + if(input > 'Z') return input - 'W'; + else if(input > '9') return input - '7'; + else return input - '0'; +} + +int ihex_parse(char input[], ihex_record_t *record) { + //given a NULL-TERMINATED input string (use gets()) in I16HEX format, write the binary record in record. return 0 on success. + + uint8_t inputlen; + uint8_t t, i, checksum_calc=0, checksum_read; + + //first check for ":" leading character + if(input[0] != ':') return -1; + + //then check the string for only valid ASCII ['0'-'F'] + inputlen=1; + while(input[inputlen]) { + if( !isxdigit(input[inputlen++]) ) return -2; + } + + //then read the length. + record->length = (asc2nibble(input[1]) << 4) + asc2nibble(input[2]); + if(input[(record->length<<1) + 11] != 0) return -3; //if we're missing a null terminator in the right place + + //then read the address. + record->addr = (asc2nibble(input[3]) << 12) + (asc2nibble(input[4]) << 8) + (asc2nibble(input[5]) << 4) + asc2nibble(input[6]); + + //then read the record type. + record->type = (asc2nibble(input[7]) << 4) + asc2nibble(input[8]); +// if(record->type > 4) return -4; + + //then read the data, which goes from input[9] to input[9+length*2]. + for(i=0; i < record->length; i++) { + t = 9 + (i<<1); + record->data[i] = (asc2nibble(input[t]) << 4) + (asc2nibble(input[t + 1])); + checksum_calc += record->data[i]; //might as well keep a running checksum as we read + } + checksum_calc += record->length + record->type + (record->addr >> 8) + (record->addr & 0xFF); //get the rest of the data into that checksum + checksum_calc = ~checksum_calc + 1; //checksum is 2's complement + + //now read the checksum of the record + checksum_read = (asc2nibble(input[9 + (record->length<<1)]) << 4) + asc2nibble(input[10 + (record->length<<1)]); + if(checksum_calc != checksum_read) return -5; //compare 'em + + return 0; +} diff --git a/firmware/microblaze/lib/ihex.h b/firmware/microblaze/lib/ihex.h new file mode 100644 index 000000000..9f471fbe2 --- /dev/null +++ b/firmware/microblaze/lib/ihex.h @@ -0,0 +1,18 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +#include +#include + +typedef struct { + uint8_t type; + size_t length; + uint32_t addr; + uint8_t *data; +} ihex_record_t; + + +int ihex_parse(char input[], ihex_record_t *record); diff --git a/firmware/microblaze/lib/loader_parser.c b/firmware/microblaze/lib/loader_parser.c new file mode 100644 index 000000000..96457a164 --- /dev/null +++ b/firmware/microblaze/lib/loader_parser.c @@ -0,0 +1,324 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 "loader_parser.h" +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include "ethernet.h" +#include "qr_settings.h" + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +static spi_flash_async_state_t async_state; + + +static caldiv_eeprom_setter_t _caldiv_set_rev = NULL; +static caldiv_eeprom_setter_t _caldiv_set_ser = NULL; +static caldiv_eeprom_setter_t _caldiv_set_mod = NULL; + +void +register_caldiv_eeprom_setters(caldiv_eeprom_setter_t set_rev, + caldiv_eeprom_setter_t set_ser, + caldiv_eeprom_setter_t set_mod) +{ + _caldiv_set_rev = set_rev; + _caldiv_set_ser = set_ser; + _caldiv_set_mod = set_mod; +} + + +// big-endian +static uint32_t +get32(const unsigned char *s) +{ + return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; +} + +// big-endian +static unsigned char * +put32(unsigned char *s, uint32_t v) +{ + s[0] = (v >> 24) & 0xff; + s[1] = (v >> 16) & 0xff; + s[2] = (v >> 8) & 0xff; + s[3] = v & 0xff; + return s + 4; +} + +static bool +erased_p(uint32_t flash_addr, size_t nbytes) +{ + unsigned char buf[64]; + + size_t n; + for (size_t i = 0; i < nbytes; i += n, flash_addr += n){ + n = min(nbytes - i, sizeof(buf)); + spi_flash_read(flash_addr, n, buf); + for (size_t j = 0; j < n; j++) + if (buf[j] != 0xff) + return false; + } + return true; +} + +static bool +erase_flash(uint32_t addr, uint32_t len) +{ + if (addr % spi_flash_sector_size() != 0) + return false; + + if (len % spi_flash_sector_size() != 0) + return false; + + spi_flash_async_erase_start(&async_state, addr, len); + // FIXME? check to see if erase was successful + return true; +} + +static bool +map_slot(uint32_t slot, uint32_t *slot_start, uint32_t *slot_len, uint32_t *status) +{ + // This case doesn't require a valid flashdir, and in fact can be used as + // part of writing the intial flashdir. + if (QLD_SLOT_DOM(slot) == QLD_DOM_UNMAPPED){ + int flash_size = get_flash_size(); + if (flash_size == 0){ + *status = QLDS_FAILED; // Can't find the flash. most likely a h/w problem. + return false; + } + *slot_start = 0; + *slot_len = flash_size; + return true; + } + + const struct flashdir *fd = get_flashdir(); + if (fd == 0) + return false; + + uint32_t slot_num = QLD_SLOT_NUM(slot); + + switch(QLD_SLOT_DOM(slot)){ + case QLD_DOM_FPGA: + if (slot_num >= fd->fpga_nslots){ + *status = QLDS_INVALID_ARG; + return false; + } + *slot_start = fd->slot[slot_num + fd->fpga_slot0].start << spi_flash_log2_sector_size(); + *slot_len = fd->slot[slot_num + fd->fpga_slot0].len << spi_flash_log2_sector_size(); + return true; + + case QLD_DOM_FW: + if (slot_num >= fd->fw_nslots){ + *status = QLDS_INVALID_ARG; + return false; + } + *slot_start = fd->slot[slot_num + fd->fw_slot0].start << spi_flash_log2_sector_size(); + *slot_len = fd->slot[slot_num + fd->fw_slot0].len << spi_flash_log2_sector_size(); + return true; + + default: + *status = QLDS_INVALID_ARG; + return false; + } +} + + +static bool +check_flashdir(void) +{ + return get_flashdir() != 0; +} + +void +loader_parser(const unsigned char *input, size_t ilen, + unsigned char *output, size_t max_olen, size_t *actual_olen) +{ + //assert (max_olen >= 8); + if (!(max_olen >= 8)) + abort(); + + *actual_olen = 0; + uint32_t status = QLDS_BAD_PKT; + + uint32_t cmd = get32(input); + uint32_t nonce = get32(input+4); + uint32_t slot = 0; + uint32_t addr = 0; + uint32_t len = 0; + + if (ilen < 8){ + nonce = -1; + goto done; + } + + uint32_t slot_start; // offset in flash + uint32_t slot_len; // length in bytes + + if (ilen >= 5 * sizeof(uint32_t)){ + slot = get32(input+8); + addr = get32(input+12); + len = get32(input+16); + } + + switch (cmd){ + case QLD_FLASH_ERASE_START: + // + if (ilen != 5 * sizeof(uint32_t)) + goto done; + + if (!check_flashdir()){ + status = QLDS_BAD_FLASHDIR; + goto done; + } + if (!map_slot(slot, &slot_start, &slot_len, &status)) + goto done; + + if (QLD_SLOT_DOM(slot) != QLD_DOM_UNMAPPED){ + addr = slot_start; + len = slot_len; + } + //printf("flash_erase: addr = 0x%x, len=0x%x\n", addr, len); + + if (0 && erased_p(addr, len)){ // already erased? + async_state.first = async_state.last = async_state.current = 0; + goto ok; + } + + if (erase_flash(addr, len)) + goto ok; + + status = QLDS_FAILED; + goto done; + + + case QLD_FLASH_ERASE_POLL: + // + if (ilen != 2 * sizeof(uint32_t)) + goto done; + + if (spi_flash_async_erase_poll(&async_state)) + goto ok; + + status = QLDS_BUSY; + goto done; + + + case QLD_FLASH_WRITE: + // + if (ilen < 5 * sizeof(uint32_t)) + goto done; + + if (ilen != 5 * sizeof(uint32_t) + len) + goto done; + + if (!check_flashdir()){ + status = QLDS_BAD_FLASHDIR; + goto done; + } + if (!map_slot(slot, &slot_start, &slot_len, &status)) + goto done; + + addr += slot_start; + len = min(len, slot_len); + + if (spi_flash_program(addr, len, &input[5*sizeof(uint32_t)])) + goto ok; + + status = QLDS_FAILED; + goto done; + + + case QLD_FLASH_READ: + case QLD_MEM_READ: + case QLD_MEM_WRITE: + case QLD_GOTO: + status = QLDS_NOTIMPLEMENTED; + goto done; + + case QLD_PING: + // + if (ilen != 2 * sizeof(uint32_t)) + goto done; + goto ok; + +#if 0 + case QLD_EEPROM_SET_XXX: + // + { + uint32_t arg = get32(input+2*sizeof(uint32_t)); + uint32_t idlen = get32(input+3*sizeof(uint32_t)); + uint8_t *idstr = (uint8_t*)input+4*sizeof(uint32_t); + uint8_t *data_p = idstr+idlen; + + //handle the ethernet cases + if (strncmp((char*)idstr, "ip", idlen) == 0){ + struct ip_addr addr = {get32(data_p)}; + ethernet_set_ip_addr(arg, addr); + } + else if (strncmp((char*)idstr, "mac", idlen) == 0){ + eth_mac_addr_t addr; + memcpy(&addr, data_p, sizeof(addr)); + ethernet_set_mac_addr(arg, &addr); + } + //handle the main board eeprom + else if (strncmp((char*)idstr, "qrrev", idlen) == 0){ + qr_set_revision(get32(data_p)); + } + else if (strncmp((char*)idstr, "qrser", idlen) == 0){ + qr_set_serial(get32(data_p)); + } + else if (strncmp((char*)idstr, "qrmod", idlen) == 0){ + qr_set_model(get32(data_p)); + } + //handle the caldiv eeprom + else if (strncmp((char*)idstr, "cdrev", idlen) == 0){ + if (_caldiv_set_rev) _caldiv_set_rev(get32(data_p)); + } + else if (strncmp((char*)idstr, "cdser", idlen) == 0){ + if (_caldiv_set_ser) _caldiv_set_ser(get32(data_p)); + } + else if (strncmp((char*)idstr, "cdmod", idlen) == 0){ + if (_caldiv_set_ser) _caldiv_set_mod(get32(data_p)); + } + else { + goto done; + } + } + goto ok; +#endif + + default: + status = QLDS_UNKNOWN_CMD; + goto done; + } + + ok: + status = QLDS_OK; + + done: + put32(output, nonce); + put32(output+4, status); + *actual_olen = 2*sizeof(uint32_t); +} diff --git a/firmware/microblaze/lib/loader_parser.h b/firmware/microblaze/lib/loader_parser.h new file mode 100644 index 000000000..365317bd7 --- /dev/null +++ b/firmware/microblaze/lib/loader_parser.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 + +/* + * max_olen must be at least 8 bytes. 1KB is recommended. + */ +void +loader_parser(const unsigned char *input, size_t ilen, + unsigned char *output, size_t max_olen, size_t *actual_olen); + +/* + * Major kludge-master altert! + * This function registers functions for setting caldiv eeprom stuff. + * This way, the parser does not depend on the qpn apps at compile time. + */ +typedef void(*caldiv_eeprom_setter_t)(uint32_t); +void register_caldiv_eeprom_setters( + caldiv_eeprom_setter_t set_rev, + caldiv_eeprom_setter_t set_ser, + caldiv_eeprom_setter_t set_mod); diff --git a/firmware/microblaze/lib/net/.gitignore b/firmware/microblaze/lib/net/.gitignore new file mode 100644 index 000000000..282522db0 --- /dev/null +++ b/firmware/microblaze/lib/net/.gitignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/firmware/microblaze/lib/net/eth_mac_addr.h b/firmware/microblaze/lib/net/eth_mac_addr.h new file mode 100644 index 000000000..b44fb68f7 --- /dev/null +++ b/firmware/microblaze/lib/net/eth_mac_addr.h @@ -0,0 +1,29 @@ +/* + * Copyright 2009 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 . + */ + +#ifndef INCLUDED_ETH_MAC_ADDR_H +#define INCLUDED_ETH_MAC_ADDR_H + +#include + +// Ethernet MAC address + +typedef struct { + uint8_t addr[6]; +} eth_mac_addr_t; + +#endif /* INCLUDED_ETH_MAC_ADDR_H */ diff --git a/firmware/microblaze/lib/net/padded_eth_hdr.h b/firmware/microblaze/lib/net/padded_eth_hdr.h new file mode 100644 index 000000000..df816734f --- /dev/null +++ b/firmware/microblaze/lib/net/padded_eth_hdr.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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 . + */ +#ifndef INCLUDED_PADDED_ETH_HDR_H +#define INCLUDED_PADDED_ETH_HDR_H + +#include +#include + +/*! + * \brief Standard 14-byte ethernet header plus two leading bytes of padding. + * + * This is what a buffer contains in line 1 when using the "slow mode" + */ +typedef struct { + uint16_t pad; + eth_mac_addr_t dst; + eth_mac_addr_t src; + uint16_t ethertype; +} _AL4 padded_eth_hdr_t; + + +#endif /* INCLUDED_PADDED_ETH_HDR_H */ diff --git a/firmware/microblaze/lib/net/socket_address.h b/firmware/microblaze/lib/net/socket_address.h new file mode 100644 index 000000000..336f30a0c --- /dev/null +++ b/firmware/microblaze/lib/net/socket_address.h @@ -0,0 +1,41 @@ +/* -*- c -*- */ +/* + * 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 . + */ +#ifndef INCLUDED_SOCKET_ADDRESS_H +#define INCLUDED_SOCKET_ADDRESS_H + +#include + +// port and address are in network byte order + +typedef struct socket_address { + unsigned short port; + struct ip_addr addr; +} socket_address_t; + +static inline struct socket_address +make_socket_address(struct ip_addr addr, int port) +{ + struct socket_address r; + r.port = port; + r.addr = addr; + return r; +} + + + +#endif /* INCLUDED_SOCKET_ADDRESS_H */ diff --git a/firmware/microblaze/lib/nonstdio.c b/firmware/microblaze/lib/nonstdio.c index 1c991afee..4b5fa4123 100644 --- a/firmware/microblaze/lib/nonstdio.c +++ b/firmware/microblaze/lib/nonstdio.c @@ -78,3 +78,46 @@ puthex32_nl(unsigned long x) puthex32(x); newline(); } +/* +void reverse(char s[]) +{ + int c, i, j; + + for (i = 0, j = strlen(s)-1; i= 0) ? value : 0-value; +} + +//we'll keep the puthex functions above because they're way more lightweight. but sometimes you just want to print in decimal, you know? +char *itoa(signed long value, char *result, int base) +{ + // check that the base if valid + if (base < 2 || base > 16) { *result = 0; return result; } + + char* out = result; + signed long quotient = value; + + do { + *out = hex[ abs(quotient % base) ]; + ++out; + quotient /= base; + } while ( quotient ); + + // Only apply negative sign for base 10 + if ( value < 0 && base == 10) *out++ = '-'; + + *out = 0; + reverse( result ); + + return result; + +} +*/ + + diff --git a/firmware/microblaze/lib/nonstdio.h b/firmware/microblaze/lib/nonstdio.h index 3fd9e39bb..62ebfa46d 100644 --- a/firmware/microblaze/lib/nonstdio.h +++ b/firmware/microblaze/lib/nonstdio.h @@ -1,4 +1,6 @@ -/* -*- c -*- */ +// +// Copyright 2010 Ettus Research LLC +// /* * Copyright 2007 Free Software Foundation, Inc. * @@ -20,7 +22,7 @@ #define INCLUDED_NONSTDIO_H #include -#include +#include #include void putstr(const char *s); // cf puts, no added newline @@ -37,10 +39,10 @@ void puthex32_nl(unsigned long x); void newline(); // putchar('\n') void print_mac_addr(const unsigned char addr[6]); -void print_fxpt_freq(u2_fxpt_freq_t v); -void print_fxpt_gain(u2_fxpt_gain_t v); void print_uint64(uint64_t v); void print_buffer(uint32_t *buf, size_t n); +//char *itoa(signed long value, char *result, int base); +//void reverse(char s[]); #endif /* INCLUDED_NONSTDIO_H */ diff --git a/firmware/microblaze/lib/spi.h b/firmware/microblaze/lib/spi.h index f5b69b270..01e4d26fd 100644 --- a/firmware/microblaze/lib/spi.h +++ b/firmware/microblaze/lib/spi.h @@ -48,5 +48,23 @@ void spi_wait(void); uint32_t spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags); +// ---------------------------------------------------------------- +// Routines that manipulate the FLASH SPI BUS +// ---------------------------------------------------------------- + +/*! + * \brief One time call to initialize SPI + */ +void spif_init(void); + +/*! + * \brief Wait for last SPI transaction to complete. + * Unless you need to know it completed, it's not necessary to call this. + */ +void spif_wait(void); + +uint32_t +spif_transact(bool readback_, int slave, uint32_t data, int length, uint32_t flags); + #endif /* INCLUDED_SPI_H */ diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index 6809101c0..ff558d673 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -25,9 +25,7 @@ #include "i2c.h" #include "mdelay.h" #include "clocks.h" -#include "usrp2_i2c_addr.h" - -//#include "nonstdio.h" +#include "usrp2/fw_common.h" unsigned char u2_hw_rev_major; unsigned char u2_hw_rev_minor; @@ -35,8 +33,8 @@ unsigned char u2_hw_rev_minor; static inline void get_hw_rev(void) { - bool ok = eeprom_read(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &u2_hw_rev_minor, 1); - ok &= eeprom_read(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &u2_hw_rev_major, 1); + bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_LSB, &u2_hw_rev_minor, 1); + ok &= eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, &u2_hw_rev_major, 1); } /* diff --git a/firmware/microblaze/lib/udp_burner_packet.c b/firmware/microblaze/lib/udp_burner_packet.c new file mode 100644 index 000000000..d86a4cf4a --- /dev/null +++ b/firmware/microblaze/lib/udp_burner_packet.c @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "udp_burner_packet.h" +#include "net_common.h" +#include "loader_parser.h" +#include +#include +#include + + +void +handle_udp_burner_packet(struct socket_address src, struct socket_address dst, + unsigned char *payload, int payload_len) +{ + unsigned char reply[128] _AL4; + size_t actual_reply_len; + loader_parser(payload, payload_len, reply, sizeof(reply), &actual_reply_len); + send_udp_pkt(dst.port, src, reply, actual_reply_len); +} diff --git a/firmware/microblaze/lib/udp_burner_packet.h b/firmware/microblaze/lib/udp_burner_packet.h new file mode 100644 index 000000000..0f4025712 --- /dev/null +++ b/firmware/microblaze/lib/udp_burner_packet.h @@ -0,0 +1,28 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 . + */ +#ifndef INCLUDED_UDP_BURNER_PACKET_H +#define INCLUDED_UDP_BURNER_PACKET_H + +#include + +void +handle_udp_burner_packet(struct socket_address src, struct socket_address dst, + unsigned char *payload, int payload_len); + + +#endif /* INCLUDED_UDP_BURNER_PACKET_H */ diff --git a/firmware/microblaze/lib/xilinx_s3_icap.c b/firmware/microblaze/lib/xilinx_s3_icap.c new file mode 100644 index 000000000..8aa7fd297 --- /dev/null +++ b/firmware/microblaze/lib/xilinx_s3_icap.c @@ -0,0 +1,101 @@ +/* -*- c -*- */ +/* + * Copyright 2009 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 . + */ + + +/* Changes required to work for the Spartan-3A series: + * The ICAP interface on the 3A is 8 bits wide, instead of 32. + * Everything is Xilinx standard LSB-first. + * The operations are all different. + * Commands are 16 bits long, presented to the ICAP interface 8 bits at a time. +*/ + +#include +#include +#include //for READ_CMD + + +/* bit swap end-for-end */ +static unsigned char +swap8(unsigned char x) +{ + unsigned char r = 0; + r |= (x >> 7) & 0x01; + r |= (x >> 5) & 0x02; + r |= (x >> 3) & 0x04; + r |= (x >> 1) & 0x08; + + r |= (x << 1) & 0x10; + r |= (x << 3) & 0x20; + r |= (x << 5) & 0x40; + r |= (x << 7) & 0x80; + + return r; +} + +void +wr_icap(uint8_t x) +{ + uint8_t t = swap8(x); + + icap_regs->icap = t; //DEBUG: does not swap bits +} + +uint8_t +rd_icap(void) +{ + return swap8(icap_regs->icap); +} + + +void +icap_reload_fpga(uint32_t flash_address) +//this DOES NOT WORK right now. reboot is not getting executed correctly. +{ + union { + uint32_t i; + uint8_t c[4]; + } t; + t.i = flash_address; + + //note! t.c[0] MUST contain the byte-wide read command for the flash device used. + //for the 25P64, and most other flash devices, this is 0x03. + t.c[0] = READ_CMD; //legacy command, use FAST_READ_CMD 0x0B after testing + + //TODO: look up the watchdog timer, ensure it won't fire too soon + + //UG332 p279 +// wr_icap(0xff); +// wr_icap(0xff); //dummy word, probably unnecessary + wr_icap(0xAA); + wr_icap(0x99); //sync word + wr_icap(0x32); + wr_icap(0x61); //Type 1 write General 1 (1 word) + wr_icap(t.c[2]); //bits 15-8 + wr_icap(t.c[3]); //bits 7-0 + wr_icap(0x32); + wr_icap(0x81); //Type 1 write General 2 (1 word) + wr_icap(t.c[0]); //C0-C8, the byte-wide read command + wr_icap(t.c[1]); //Upper 8 bits of 24-bit address + wr_icap(0x30); + wr_icap(0xA1); //Type 1 write CMD (1 word) + wr_icap(0x00); + wr_icap(0x0E); //REBOOT command + wr_icap(0x20); + wr_icap(0x00); //Type 1 NOP + +} diff --git a/firmware/microblaze/usrp2/.gitignore b/firmware/microblaze/usrp2/.gitignore new file mode 100644 index 000000000..18f715618 --- /dev/null +++ b/firmware/microblaze/usrp2/.gitignore @@ -0,0 +1,9 @@ +/Makefile +/Makefile.in +/*.a +/*.bin +/*.dump +/*.ihx +/*.elf +/*.rom +/*.map diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am new file mode 100644 index 000000000..859ded9e5 --- /dev/null +++ b/firmware/microblaze/usrp2/Makefile.am @@ -0,0 +1,43 @@ +# +# 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 $(top_srcdir)/Makefile.common + +AM_CFLAGS = \ + $(COMMON_CFLAGS) + +AM_LDFLAGS = \ + $(COMMON_LFLAGS) \ + libusrp2.a \ + -Wl,-defsym -Wl,_TEXT_START_ADDR=0x0050 \ + -Wl,-defsym -Wl,_STACK_SIZE=3072 + +######################################################################## +# USRP2 specific library and programs +######################################################################## +noinst_LIBRARIES = libusrp2.a + +libusrp2_a_SOURCES = \ + $(COMMON_SRCS) \ + clocks.c \ + sd.c + +noinst_PROGRAMS = \ + usrp2_txrx_uhd.elf + +usrp2_txrx_uhd_elf_SOURCES = \ + $(top_srcdir)/apps/txrx_uhd.c diff --git a/firmware/microblaze/usrp2/clocks.c b/firmware/microblaze/usrp2/clocks.c new file mode 100644 index 000000000..ccc4a7cc7 --- /dev/null +++ b/firmware/microblaze/usrp2/clocks.c @@ -0,0 +1,239 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include "memory_map.h" +#include "ad9510.h" +#include "spi.h" +#include "u2_init.h" +#include "nonstdio.h" + +void +clocks_init(void) +{ + // Set up basic clocking functions in AD9510 + ad9510_write_reg(0x45, 0x00); // CLK2 drives distribution + + clocks_enable_fpga_clk(true, 1); + + spi_wait(); + + // Set up PLL for 10 MHz reference + // Reg 4, A counter, Don't Care + ad9510_write_reg(0x05, 0x00); // Reg 5, B counter MSBs, 0 + ad9510_write_reg(0x06, 0x05); // Reg 6, B counter LSBs, 5 + // Reg 7, Loss of reference detect, doesn't work yet, 0 + ad9510_write_reg(0x5A, 0x01); // Update Regs + + // Primary clock configuration + clocks_mimo_config(MC_WE_DONT_LOCK); + + // Set up other clocks + //clocks_enable_test_clk(false, 0); + //clocks_enable_tx_dboard(false, 0); + //clocks_enable_rx_dboard(false, 0); + clocks_enable_eth_phyclk(false, 0); + + // Enable clock to ADCs and DACs + //clocks_enable_dac_clk(true, 1); + //clocks_enable_adc_clk(true, 1); +} + + +void +clocks_mimo_config(int flags) +{ + if (flags & _MC_WE_LOCK){ + // Reg 8, Charge pump on, dig lock det, positive PFD, 47 + ad9510_write_reg(0x08, 0x47); + } + else { + // Reg 8, Charge pump off, dig lock det, positive PFD + ad9510_write_reg(0x08, 0x00); + } + + // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA + ad9510_write_reg(0x09, 0x00); + // Reg A, Prescaler of 2, everything normal 04 + ad9510_write_reg(0x0A, 0x04); + // Reg B, R Div MSBs, 0 + ad9510_write_reg(0x0B, 0x00); + // Reg C, R Div LSBs, 1 + ad9510_write_reg(0x0C, 0x01); + // Reg D, Antibacklash, Digital lock det, 0 + + ad9510_write_reg(0x5A, 0x01); // Update Regs + + spi_wait(); + + // Allow for clock switchover + + if (flags & _MC_WE_LOCK){ // WE LOCK + if (flags & _MC_MIMO_CLK_INPUT) { + // Turn on ref output and choose the MIMO connector + output_regs->clk_ctrl = 0x15; + } + else { + // turn on ref output and choose the SMA + output_regs->clk_ctrl = 0x1C; + } + } + else { // WE DONT LOCK + // Disable both ext clk inputs + output_regs->clk_ctrl = 0x10; + } + + // Do we drive a clock onto the MIMO connector? + if (flags & MC_PROVIDE_CLK_TO_MIMO) + clocks_enable_clkexp_out(true,10); + else + clocks_enable_clkexp_out(false,0); +} + +bool +clocks_lock_detect() +{ + if(pic_regs->pending & PIC_CLKSTATUS) + return true; + return false; +} + +int inline +clocks_gen_div(int divisor) +{ + int L,H; + L = (divisor>>1)-1; + H = divisor-L-2; + return (L<<4)|H; +} + +#define CLOCK_OUT_EN 0x08 +#define CLOCK_OUT_DIS_CMOS 0x01 +#define CLOCK_OUT_DIS_PECL 0x02 +#define CLOCK_DIV_DIS 0x80 +#define CLOCK_DIV_EN 0x00 + +#define CLOCK_MODE_PECL 1 +#define CLOCK_MODE_LVDS 2 +#define CLOCK_MODE_CMOS 3 + +void +clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mode) +{ + int enable_word, div_word, div_en_word; + + switch(mode) { + case CLOCK_MODE_PECL : + enable_word = enable ? 0x08 : 0x0A; + break; + case CLOCK_MODE_LVDS : + enable_word = enable ? 0x02 : 0x03; + break; + case CLOCK_MODE_CMOS : + enable_word = enable ? 0x08 : 0x09; + break; + } + if(enable && (divisor>1)) { + div_word = clocks_gen_div(divisor); + div_en_word = CLOCK_DIV_EN; + } + else { + div_word = 0; + div_en_word = CLOCK_DIV_DIS; + } + + ad9510_write_reg(reg_en,enable_word); // Output en/dis + ad9510_write_reg(reg_div,div_word); // Set divisor + ad9510_write_reg(reg_div+1,div_en_word); // Enable or Bypass Divider + ad9510_write_reg(0x5A, 0x01); // Update Regs +} + +// Clock 0 +/*void +clocks_enable_test_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL); +}*/ + +// Clock 1 +void +clocks_enable_fpga_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL); +} + +// Clock 2 on Rev 3, Clock 5 on Rev 4 +void +clocks_enable_clkexp_out(bool enable, int divisor) +{ + if(u2_hw_rev_major == 3) + clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); + else if(u2_hw_rev_major == 4) { + ad9510_write_reg(0x34,0x00); // Turn on fine delay + ad9510_write_reg(0x35,0x00); // Set Full Scale to nearly 10ns + ad9510_write_reg(0x36,0x1c); // Set fine delay. 0x20 is midscale + clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); + + } + else + putstr("ERR: Invalid Rev\n"); +} + +// Clock 5 on Rev 3, none (was 2) on Rev 4 +void +clocks_enable_eth_phyclk(bool enable, int divisor) +{ + if(u2_hw_rev_major == 3) + clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); + else if(u2_hw_rev_major == 4) + clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); + else + putstr("ERR: Invalid Rev\n"); +} + +// Clock 3 +/*void +clocks_enable_dac_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL); +}*/ + +// Clock 4 +/*void +clocks_enable_adc_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS); +}*/ + +// Clock 6 +/*void +clocks_enable_tx_dboard(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS); +}*/ + +// Clock 7 +/*void +clocks_enable_rx_dboard(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS); +}*/ diff --git a/firmware/microblaze/usrp2/memory_map.h b/firmware/microblaze/usrp2/memory_map.h new file mode 100644 index 000000000..4c9ead615 --- /dev/null +++ b/firmware/microblaze/usrp2/memory_map.h @@ -0,0 +1,793 @@ +/* -*- c -*- */ +/* + * Copyright 2007,2008,2009 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, see . + */ + +/* Overall Memory Map + * 0000-7FFF 32K RAM space (16K on 1500, 24K on 2000, 32K on DSP) + * 8000-BFFF 16K Buffer Pool + * C000-FFFF 16K Peripherals + */ + + +#ifndef INCLUDED_MEMORY_MAP_H +#define INCLUDED_MEMORY_MAP_H + +#include + + +#define MASTER_CLK_RATE 100000000 // 100 MHz + + +//////////////////////////////////////////////////////////////// +// +// Memory map for embedded wishbone bus +// +//////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////// +// Main RAM, Slave 0 + +#define RAM_BASE 0x0000 + +//////////////////////////////////////////////////////////////// +// Buffer Pool RAM, Slave 1 +// +// The buffers themselves are located in Slave 1, Buffer Pool RAM. +// The status registers are in Slave 5, Buffer Pool Status. +// The control register is in Slave 7, Settings Bus. + +#define BUFFER_POOL_RAM_BASE 0x8000 + +#define NBUFFERS 8 +#define BP_NLINES 0x0200 // number of 32-bit lines in a buffer +#define BP_LAST_LINE (BP_NLINES - 1) // last line in a buffer + +#define buffer_pool_ram \ + ((uint32_t *) BUFFER_POOL_RAM_BASE) + +#define buffer_ram(n) (&buffer_pool_ram[(n) * BP_NLINES]) + + +///////////////////////////////////////////////////// +// SPI Core, Slave 2. See core docs for more info +#define SPI_BASE 0xC000 // Base address (16-bit) + +typedef struct { + volatile uint32_t txrx0; + volatile uint32_t txrx1; + volatile uint32_t txrx2; + volatile uint32_t txrx3; + volatile uint32_t ctrl; + volatile uint32_t div; + volatile uint32_t ss; +} spi_regs_t; + +#define spi_regs ((spi_regs_t *) SPI_BASE) + + +// Masks for controlling different peripherals +#define SPI_SS_AD9510 1 +#define SPI_SS_AD9777 2 +#define SPI_SS_RX_DAC 4 +#define SPI_SS_RX_ADC 8 +#define SPI_SS_RX_DB 16 +#define SPI_SS_TX_DAC 32 +#define SPI_SS_TX_ADC 64 +#define SPI_SS_TX_DB 128 +#define SPI_SS_ADS64P44 256 + +// Masks for different parts of CTRL reg +#define SPI_CTRL_ASS (1<<13) +#define SPI_CTRL_IE (1<<12) +#define SPI_CTRL_LSB (1<<11) +#define SPI_CTRL_TXNEG (1<<10) +#define SPI_CTRL_RXNEG (1<< 9) +#define SPI_CTRL_GO_BSY (1<< 8) +#define SPI_CTRL_CHAR_LEN_MASK 0x7F + +//////////////////////////////////////////////// +// I2C, Slave 3 +// See Wishbone I2C-Master Core Specification. + +#define I2C_BASE 0xC400 + +typedef struct { + volatile uint32_t prescaler_lo; // r/w + volatile uint32_t prescaler_hi; // r/w + volatile uint32_t ctrl; // r/w + volatile uint32_t data; // wr = transmit reg; rd = receive reg + volatile uint32_t cmd_status; // wr = command reg; rd = status reg +} i2c_regs_t; + +#define i2c_regs ((i2c_regs_t *) I2C_BASE) + +#define I2C_CTRL_EN (1 << 7) // core enable +#define I2C_CTRL_IE (1 << 6) // interrupt enable + +// +// STA, STO, RD, WR, and IACK bits are cleared automatically +// +#define I2C_CMD_START (1 << 7) // generate (repeated) start condition +#define I2C_CMD_STOP (1 << 6) // generate stop condition +#define I2C_CMD_RD (1 << 5) // read from slave +#define I2C_CMD_WR (1 << 4) // write to slave +#define I2C_CMD_NACK (1 << 3) // when a rcvr, send ACK (ACK=0) or NACK (ACK=1) +#define I2C_CMD_RSVD_2 (1 << 2) // reserved +#define I2C_CMD_RSVD_1 (1 << 1) // reserved +#define I2C_CMD_IACK (1 << 0) // set to clear pending interrupt + +#define I2C_ST_RXACK (1 << 7) // Received acknowledgement from slave (1 = NAK, 0 = ACK) +#define I2C_ST_BUSY (1 << 6) // 1 after START signal detected; 0 after STOP signal detected +#define I2C_ST_AL (1 << 5) // Arbitration lost. 1 when core lost arbitration +#define I2C_ST_RSVD_4 (1 << 4) // reserved +#define I2C_ST_RSVD_3 (1 << 3) // reserved +#define I2C_ST_RSVD_2 (1 << 2) // reserved +#define I2C_ST_TIP (1 << 1) // Transfer-in-progress +#define I2C_ST_IP (1 << 0) // Interrupt pending + + +//////////////////////////////////////////////// +// GPIO, Slave 4 +// +// These go to the daughterboard i/o pins + +#define GPIO_BASE 0xC800 + +typedef struct { + volatile uint32_t io; // tx data in high 16, rx in low 16 + volatile uint32_t ddr; // 32 bits, 1 means output. tx in high 16, rx in low 16 + volatile uint32_t tx_sel; // 16 2-bit fields select which source goes to TX DB + volatile uint32_t rx_sel; // 16 2-bit fields select which source goes to RX DB +} gpio_regs_t; + +// each 2-bit sel field is layed out this way +#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg +#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic +#define GPIO_SEL_DEBUG_0 2 // if pin is an output, debug lines from FPGA fabric +#define GPIO_SEL_DEBUG_1 3 // if pin is an output, debug lines from FPGA fabric + +#define gpio_base ((gpio_regs_t *) GPIO_BASE) + +/////////////////////////////////////////////////// +// Buffer Pool Status, Slave 5 +// +// The buffers themselves are located in Slave 1, Buffer Pool RAM. +// The status registers are in Slave 5, Buffer Pool Status. +// The control register is in Slave 7, Settings Bus. + +#define BUFFER_POOL_STATUS_BASE 0xCC00 + +typedef struct { + volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer + volatile uint32_t status; // error and done flags + volatile uint32_t hw_config; // see below + volatile uint32_t dummy[3]; + volatile uint32_t irqs; + volatile uint32_t pri_enc_bp_status; + volatile uint32_t cycle_count; +} buffer_pool_status_t; + +#define buffer_pool_status ((buffer_pool_status_t *) BUFFER_POOL_STATUS_BASE) + +/* + * Buffer n's xfer is done. + * Clear this bit by issuing bp_clear_buf(n) + */ +#define BPS_DONE(n) (0x00000001 << (n)) +#define BPS_DONE_0 BPS_DONE(0) +#define BPS_DONE_1 BPS_DONE(1) +#define BPS_DONE_2 BPS_DONE(2) +#define BPS_DONE_3 BPS_DONE(3) +#define BPS_DONE_4 BPS_DONE(4) +#define BPS_DONE_5 BPS_DONE(5) +#define BPS_DONE_6 BPS_DONE(6) +#define BPS_DONE_7 BPS_DONE(7) + +/* + * Buffer n's xfer had an error. + * Clear this bit by issuing bp_clear_buf(n) + */ +#define BPS_ERROR(n) (0x00000100 << (n)) +#define BPS_ERROR_0 BPS_ERROR(0) +#define BPS_ERROR_1 BPS_ERROR(1) +#define BPS_ERROR_2 BPS_ERROR(2) +#define BPS_ERROR_3 BPS_ERROR(3) +#define BPS_ERROR_4 BPS_ERROR(4) +#define BPS_ERROR_5 BPS_ERROR(5) +#define BPS_ERROR_6 BPS_ERROR(6) +#define BPS_ERROR_7 BPS_ERROR(7) + +/* + * Buffer n is idle. A buffer is idle if it's not + * DONE, ERROR, or processing a transaction. If it's + * IDLE, it's safe to start a new transaction. + * + * Clear this bit by starting a xfer with + * bp_send_from_buf or bp_receive_to_buf. + */ +#define BPS_IDLE(n) (0x00010000 << (n)) +#define BPS_IDLE_0 BPS_IDLE(0) +#define BPS_IDLE_1 BPS_IDLE(1) +#define BPS_IDLE_2 BPS_IDLE(2) +#define BPS_IDLE_3 BPS_IDLE(3) +#define BPS_IDLE_4 BPS_IDLE(4) +#define BPS_IDLE_5 BPS_IDLE(5) +#define BPS_IDLE_6 BPS_IDLE(6) +#define BPS_IDLE_7 BPS_IDLE(7) + +/* + * Buffer n has a "slow path" packet in it. + * This bit is orthogonal to the bits above and indicates that + * the FPGA ethernet rx protocol engine has identified this packet + * as one requiring firmware intervention. + */ +#define BPS_SLOWPATH(n) (0x01000000 << (n)) +#define BPS_SLOWPATH_0 BPS_SLOWPATH(0) +#define BPS_SLOWPATH_1 BPS_SLOWPATH(1) +#define BPS_SLOWPATH_2 BPS_SLOWPATH(2) +#define BPS_SLOWPATH_3 BPS_SLOWPATH(3) +#define BPS_SLOWPATH_4 BPS_SLOWPATH(4) +#define BPS_SLOWPATH_5 BPS_SLOWPATH(5) +#define BPS_SLOWPATH_6 BPS_SLOWPATH(6) +#define BPS_SLOWPATH_7 BPS_SLOWPATH(7) + + +#define BPS_DONE_ALL 0x000000ff // mask of all dones +#define BPS_ERROR_ALL 0x0000ff00 // mask of all errors +#define BPS_IDLE_ALL 0x00ff0000 // mask of all idles +#define BPS_SLOWPATH_ALL 0xff000000 // mask of all slowpaths + +// The hw_config register + +#define HWC_SIMULATION 0x80000000 +#define HWC_WB_CLK_DIV_MASK 0x0000000f + +/*! + * \brief return non-zero if we're running under the simulator + */ +inline static int +hwconfig_simulation_p(void) +{ + return buffer_pool_status->hw_config & HWC_SIMULATION; +} + +/*! + * \brief Return Wishbone Clock divisor. + * The processor runs at the Wishbone Clock rate which is MASTER_CLK_RATE / divisor. + */ +inline static int +hwconfig_wishbone_divisor(void) +{ + return buffer_pool_status->hw_config & HWC_WB_CLK_DIV_MASK; +} + +/////////////////////////////////////////////////// +// Ethernet Core, Slave 6 + +#define ETH_BASE 0xD000 + +#include "eth_mac_regs.h" + +#define eth_mac ((eth_mac_regs_t *) ETH_BASE) + +//////////////////////////////////////////////////// +// Settings Bus, Slave #7, Not Byte Addressable! +// +// Output-only from processor point-of-view. +// 1KB of address space (== 256 32-bit write-only regs) + + +#define MISC_OUTPUT_BASE 0xD400 +#define TX_PROTOCOL_ENGINE_BASE 0xD480 +#define RX_PROTOCOL_ENGINE_BASE 0xD4C0 +#define BUFFER_POOL_CTRL_BASE 0xD500 +#define LAST_SETTING_REG 0xD7FC // last valid setting register + +#define SR_MISC 0 +#define SR_TX_PROT_ENG 32 +#define SR_RX_PROT_ENG 48 +#define SR_BUFFER_POOL_CTRL 64 +#define SR_UDP_SM 96 +#define SR_TX_DSP 208 +#define SR_TX_CTRL 224 +#define SR_RX_DSP 160 +#define SR_RX_CTRL 176 +#define SR_TIME64 192 +#define SR_SIMTIMER 198 +#define SR_LAST 255 + +#define _SR_ADDR(sr) (MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t)) + +// --- buffer pool control regs --- + +typedef struct { + volatile uint32_t ctrl; +} buffer_pool_ctrl_t; + +// buffer pool ports + +#define PORT_SERDES 0 // serial/deserializer +#define PORT_DSP 1 // DSP tx or rx pipeline +#define PORT_ETH 2 // ethernet tx or rx +#define PORT_RAM 3 // RAM tx or rx + +// the buffer pool ctrl register fields + +#define BPC_BUFFER(n) (((n) & 0xf) << 28) +#define BPC_BUFFER_MASK BPC_BUFFER(~0) +#define BPC_BUFFER_0 BPC_BUFFER(0) +#define BPC_BUFFER_1 BPC_BUFFER(1) +#define BPC_BUFFER_2 BPC_BUFFER(2) +#define BPC_BUFFER_3 BPC_BUFFER(3) +#define BPC_BUFFER_4 BPC_BUFFER(4) +#define BPC_BUFFER_5 BPC_BUFFER(5) +#define BPC_BUFFER_6 BPC_BUFFER(6) +#define BPC_BUFFER_7 BPC_BUFFER(7) +#define BPC_BUFFER_NIL BPC_BUFFER(0x8) // disable + +#define BPC_PORT(n) (((n) & 0x7) << 25) +#define BPC_PORT_MASK BPC_PORT(~0) +#define BPC_PORT_SERDES BPC_PORT(PORT_SERDES) +#define BPC_PORT_DSP BPC_PORT(PORT_DSP) +#define BPC_PORT_ETH BPC_PORT(PORT_ETH) +#define BPC_PORT_RAM BPC_PORT(PORT_RAM) +#define BPC_PORT_NIL BPC_PORT(0x4) // disable + +#define BPC_CLR (1 << 24) // mutually excl commands +#define BPC_READ (1 << 23) +#define BPC_WRITE (1 << 22) + +#define BPC_STEP(step) (((step) & 0xf) << 18) +#define BPC_STEP_MASK BPC_STEP(~0) +#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9) +#define BPC_LAST_LINE_MASK BPC_LAST_LINE(~0) +#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0) +#define BPC_FIRST_LINE_MASK BPC_FIRST_LINE(~0) + +#define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE) + +// --- misc outputs --- + +typedef struct { + volatile uint32_t clk_ctrl; + volatile uint32_t serdes_ctrl; + volatile uint32_t adc_ctrl; + volatile uint32_t leds; + volatile uint32_t phy_ctrl; // LSB is reset line to eth phy + volatile uint32_t debug_mux_ctrl; + volatile uint32_t ram_page; // FIXME should go somewhere else... + volatile uint32_t flush_icache; // Flush the icache + volatile uint32_t led_src; // HW or SW control for LEDs +} output_regs_t; + +#define SERDES_ENABLE 8 +#define SERDES_PRBSEN 4 +#define SERDES_LOOPEN 2 +#define SERDES_RXEN 1 + +#define ADC_CTRL_ON 0x0F +#define ADC_CTRL_OFF 0x00 + +// crazy order that matches the labels on the case + +#define LED_A (1 << 4) +#define LED_B (1 << 1) +#define LED_C (1 << 3) +#define LED_D (1 << 0) +#define LED_E (1 << 2) +// LED_F // controlled by CPLD +#define LED_RJ45 (1 << 5) + +#define output_regs ((output_regs_t *) MISC_OUTPUT_BASE) + +// --- udp tx regs --- + +typedef struct { + // Bits 19:16 are control info; bits 15:0 are data (see below) + // First two words are unused. + volatile uint32_t _nope[2]; + //--- ethernet header - 14 bytes--- + volatile struct{ + uint32_t mac_dst_0_1; //word 2 + uint32_t mac_dst_2_3; + uint32_t mac_dst_4_5; + uint32_t mac_src_0_1; + uint32_t mac_src_2_3; + uint32_t mac_src_4_5; + uint32_t ether_type; //word 8 + } eth_hdr; + //--- ip header - 20 bytes --- + volatile struct{ + uint32_t ver_ihl_tos; //word 9 + uint32_t total_length; + uint32_t identification; + uint32_t flags_frag_off; + uint32_t ttl_proto; + uint32_t checksum; + uint32_t src_addr_high; + uint32_t src_addr_low; + uint32_t dst_addr_high; + uint32_t dst_addr_low; //word 18 + } ip_hdr; + //--- udp header - 8 bytes --- + volatile struct{ + uint32_t src_port; //word 19 + uint32_t dst_port; + uint32_t length; + uint32_t checksum; //word 22 + } udp_hdr; + volatile uint32_t _pad[32-23]; +} sr_udp_sm_t; + +// control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) + +// This is the last word of the header +#define UDP_SM_LAST_WORD (1 << 19) + +// Insert IP header checksum here. Data is the xor of 16'hFFFF and +// the values written into regs 9-13 and 15-18. +#define UDP_SM_INS_IP_HDR_CHKSUM (1 << 18) + +// Insert IP Length here (data ignored) +#define UDP_SM_INS_IP_LEN (1 << 17) + +// Insert UDP Length here (data ignore) +#define UDP_SM_INS_UDP_LEN (1 << 16) + +#define sr_udp_sm ((sr_udp_sm_t *) _SR_ADDR(SR_UDP_SM)) + +// --- dsp tx regs --- + +#define MIN_CIC_INTERP 1 +#define MAX_CIC_INTERP 128 + +typedef struct { + volatile uint32_t num_chan; + volatile uint32_t clear_state; // clears out state machine, fifos, +} sr_tx_ctrl_t; + +#define sr_tx_ctrl ((sr_tx_ctrl_t *) _SR_ADDR(SR_TX_CTRL)) + +typedef struct { + volatile int32_t freq; + volatile uint32_t scale_iq; // {scale_i,scale_q} + volatile uint32_t interp_rate; + volatile uint32_t _padding0; // padding for the tx_mux + // NOT freq, scale, interp + /*! + * \brief output mux configuration. + * + *
+   *     3                   2                   1                       
+   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   *  +-------------------------------+-------+-------+-------+-------+
+   *  |                                               | DAC1  |  DAC0 |
+   *  +-------------------------------+-------+-------+-------+-------+
+   * 
+   *  There are N DUCs (1 now) with complex inputs and outputs.
+   *  There are two DACs.
+   * 
+   *  Each 4-bit DACx field specifies the source for the DAC
+   *  Each subfield is coded like this: 
+   * 
+   *     3 2 1 0
+   *    +-------+
+   *    |   N   |
+   *    +-------+
+   * 
+   *  N specifies which DUC output is connected to this DAC.
+   * 
+   *   N   which interp output
+   *  ---  -------------------
+   *   0   DUC 0 I
+   *   1   DUC 0 Q
+   *   2   DUC 1 I
+   *   3   DUC 1 Q
+   *   F   All Zeros
+   *   
+   * The default value is 0x10
+   * 
+ */ + volatile uint32_t tx_mux; + +} dsp_tx_regs_t; + +#define dsp_tx_regs ((dsp_tx_regs_t *) _SR_ADDR(SR_TX_DSP)) + +// --- VITA RX CTRL regs --- +typedef struct { + // The following 3 are logically a single command register. + // They are clocked into the underlying fifo when time_ticks is written. + volatile uint32_t cmd; // {now, chain, num_samples(30) + volatile uint32_t time_secs; + volatile uint32_t time_ticks; + + volatile uint32_t clear_overrun; // write anything to clear overrun + volatile uint32_t vrt_header; // word 0 of packet. FPGA fills in packet counter + volatile uint32_t vrt_stream_id; // word 1 of packet. + volatile uint32_t vrt_trailer; + volatile uint32_t nsamples_per_pkt; + volatile uint32_t nchannels; // 1 in basic case, up to 4 for vector sources + volatile uint32_t pad[7]; // Make each structure 16 elements long +} sr_rx_ctrl_t; + +#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL)) + +// --- dsp rx regs --- +#define MIN_CIC_DECIM 1 +#define MAX_CIC_DECIM 128 + +typedef struct { + volatile int32_t freq; + volatile uint32_t scale_iq; // {scale_i,scale_q} + volatile uint32_t decim_rate; + volatile uint32_t dcoffset_i; // Bit 31 high sets fixed offset mode, using lower 14 bits, + // otherwise it is automatic + volatile uint32_t dcoffset_q; // Bit 31 high sets fixed offset mode, using lower 14 bits + + /*! + * \brief input mux configuration. + * + * This determines which ADC (or constant zero) is connected to + * each DDC input. There are N DDCs (1 now). Each has two inputs. + * + *
+   * Mux value:
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   * |                                                       |Q0 |I0 |
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   *
+   * Each 2-bit I field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
+   * Each 2-bit Q field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
+   *
+   * The default value is 0x4
+   * 
+ */ + volatile uint32_t rx_mux; // called adc_mux in dsp_core_rx.v + + /*! + * \brief Streaming GPIO configuration + * + * This determines whether the LSBs of I and Q samples come from the DSP + * pipeline or from the io_rx GPIO pins. To stream GPIO, one must first + * set the GPIO data direction register to have io_rx[15] and/or io_rx[14] + * configured as inputs. The GPIO pins will be sampled at the time the + * remainder of the DSP sample is strobed into the RX sample FIFO. There + * will be a decimation-dependent fixed time offset between the GPIO + * sample stream and the associated RF samples. + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | MBZ |Q|I| + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * I 0=LSB comes from DSP pipeline (default) + * 1=LSB comes from io_rx[15] + * + * Q 0=LSB comes from DSP pipeline (default) + * 1=LSB comes from io_rx[14] + */ + volatile uint32_t gpio_stream_enable; + +} dsp_rx_regs_t; + +#define dsp_rx_regs ((dsp_rx_regs_t *) _SR_ADDR(SR_RX_DSP)) + +// ---------------------------------------------------------------- +// VITA49 64 bit time (write only) + /*! + * \brief Time 64 flags + * + *
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-----------------------------------------------------------+-+-+
+   * |                                                           |S|P|
+   * +-----------------------------------------------------------+-+-+
+   *
+   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
+   * S - Source (0=sma, 1=mimo, 0=default)
+   *
+   * 
+ */ +typedef struct { + volatile uint32_t secs; // value to set absolute secs to on next PPS + volatile uint32_t ticks; // value to set absolute ticks to on next PPS + volatile uint32_t flags; // flags - see chart above + volatile uint32_t imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0) +} sr_time64_t; + +#define sr_time64 ((sr_time64_t *) _SR_ADDR(SR_TIME64)) + + +/* + * --- ethernet tx protocol engine regs (write only) --- + * + * These registers control the transmit portion of the ethernet + * protocol engine (out of USRP2). The protocol engine handles fifo + * status and sequence number insertion in outgoing packets, and + * automagically generates status packets when required to inform the + * host of changes in fifo availability. + * + * All outgoing packets have their fifo_status field set to the number + * of 32-bit lines of fifo available in the ethernet Rx fifo (see + * usrp2_eth_packet.h). Seqno's are set if FIXME, else 0. + * + * FIXME clean this up once we know how it's supposed to behave. + */ + +typedef struct { + volatile uint32_t flags; // not yet fully defined (channel?) + volatile uint32_t mac_dst0123; // 4 bytes of destination mac addr + volatile uint32_t mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr + volatile uint32_t mac_src2345; // 4 bytes of destination mac addr + volatile uint32_t seqno; // Write to init seqno. It autoincs on match +} tx_proto_engine_regs_t; + +#define tx_proto_engine ((tx_proto_engine_regs_t *) TX_PROTOCOL_ENGINE_BASE) + +/* + * --- ethernet rx protocol engine regs (write only) --- + * + * These registers control the receive portion of the ethernet + * protocol engine (into USRP2). The protocol engine offloads common + * packet inspection operations so that firmware has less to do on + * "fast path" packets. + * + * The registers define conditions which must be matched for a packet + * to be considered a "fast path" packet. If a received packet + * matches the src and dst mac address, ethertype, flags field, and + * expected seqno number it is considered a "fast path" packet, and + * the expected seqno is updated. If the packet fails to satisfy any + * of the above conditions it's a "slow path" packet, and the + * corresponding SLOWPATH flag will be set buffer_status register. + */ + +typedef struct { + volatile uint32_t flags; // not yet fully defined (channel?) + volatile uint32_t mac_dst0123; // 4 bytes of destination mac addr + volatile uint32_t mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr + volatile uint32_t mac_src2345; // 4 bytes of destination mac addr + volatile uint32_t ethertype_pad; // ethertype in high 16-bits +} rx_proto_engine_regs_t; + +#define rx_proto_engine ((rx_proto_engine_regs_t *) RX_PROTOCOL_ENGINE_BASE) + + + +/////////////////////////////////////////////////// +// Simple Programmable Interrupt Controller, Slave 8 + +#define PIC_BASE 0xD800 + +// Interrupt request lines +// Bit numbers (LSB == 0) that correpond to interrupts into PIC + +#define IRQ_BUFFER 0 // buffer manager +#define IRQ_ONETIME 1 +#define IRQ_SPI 2 +#define IRQ_I2C 3 +#define IRQ_PHY 4 // ethernet PHY +#define IRQ_UNDERRUN 5 +#define IRQ_OVERRUN 6 +#define IRQ_PPS 7 // pulse per second +#define IRQ_UART_RX 8 +#define IRQ_UART_TX 9 +#define IRQ_SERDES 10 +#define IRQ_CLKSTATUS 11 +#define IRQ_PERIODIC 12 + +#define IRQ_TO_MASK(x) (1 << (x)) + +#define PIC_BUFFER_INT IRQ_TO_MASK(IRQ_BUFFER) +#define PIC_ONETIME_INT IRQ_TO_MASK(IRQ_ONETIME) +#define PIC_SPI_INT IRQ_TO_MASK(IRQ_SPI) +#define PIC_I2C_INT IRQ_TO_MASK(IRQ_I2C) +#define PIC_PHY_INT IRQ_TO_MASK(IRQ_PHY) +#define PIC_UNDERRUN_INT IRQ_TO_MASK(IRQ_UNDERRUN) +#define PIC_OVERRUN_INT IRQ_TO_MASK(IRQ_OVERRUN) +#define PIC_PPS_INT IRQ_TO_MASK(IRQ_PPS) +#define PIC_UART_RX_INT IRQ_TO_MASK(IRQ_UART_RX) +#define PIC_UART_TX_INT IRQ_TO_MASK(IRQ_UART_TX) +#define PIC_SERDES IRQ_TO_MASK(IRQ_SERDES) +#define PIC_CLKSTATUS IRQ_TO_MASK(IRQ_CLKSTATUS) + +typedef struct { + volatile uint32_t edge_enable; // mask: 1 -> edge triggered, 0 -> level + volatile uint32_t polarity; // mask: 1 -> rising edge + volatile uint32_t mask; // mask: 1 -> disabled + volatile uint32_t pending; // mask: 1 -> pending; write 1's to clear pending ints +} pic_regs_t; + +#define pic_regs ((pic_regs_t *) PIC_BASE) + +// ---------------------------------------------------------------- +// WB_CLK_RATE is the time base for this +typedef struct { + volatile uint32_t onetime; // Number of wb clk cycles till the onetime interrupt + volatile uint32_t periodic; // Repeat rate of periodic interrupt +} sr_simple_timer_t; + +#define sr_simple_timer ((sr_simple_timer_t *) _SR_ADDR(SR_SIMTIMER)) + +/////////////////////////////////////////////////// +// UART, Slave 10 + +#define UART_BASE 0xE000 + +typedef struct { + // All elements are 8 bits except for clkdiv (16), but we use uint32 to make + // the hardware for decoding easier + volatile uint32_t clkdiv; // Set to 50e6 divided by baud rate (no x16 factor) + volatile uint32_t txlevel; // Number of spaces in the FIFO for writes + volatile uint32_t rxlevel; // Number of available elements in the FIFO for reads + volatile uint32_t txchar; // Write characters to be sent here + volatile uint32_t rxchar; // Read received characters here +} uart_regs_t; + +#define uart_regs ((uart_regs_t *) UART_BASE) + +/////////////////////////////////////////////////// +// ATR Controller, Slave 11 + +#define ATR_BASE 0xE400 + +typedef struct { + volatile uint32_t v[16]; +} atr_regs_t; + +#define ATR_IDLE 0x0 // indicies into v +#define ATR_TX 0x1 +#define ATR_RX 0x2 +#define ATR_FULL 0x3 + +#define atr_regs ((atr_regs_t *) ATR_BASE) + +/////////////////////////////////////////////////// +// SD Card SPI interface, Slave 13 +// All regs are 8 bits wide, but are accessed as if they are 32 bits + +#define SDSPI_BASE 0xEC00 + +typedef struct { + volatile uint32_t status; // Write a 1 or 0 for controlling CS + volatile uint32_t clkdiv; + volatile uint32_t send_dat; + volatile uint32_t receive_dat; +} sdspi_regs_t; + +#define sdspi_regs ((sdspi_regs_t *) SDSPI_BASE) + +/////////////////////////////////////////////////// +// External RAM interface, Slave 14 +// Pages are 1K. Page is 10 bits, set by a control register +// output_regs->ram_page + +#define EXTRAM_BASE 0xF000 +#define extram ((volatile uint32_t *) EXTRAM_BASE) + + +/////////////////////////////////////////////////// + +#endif + diff --git a/firmware/microblaze/usrp2/sd.c b/firmware/microblaze/usrp2/sd.c new file mode 100644 index 000000000..d000b28ae --- /dev/null +++ b/firmware/microblaze/usrp2/sd.c @@ -0,0 +1,197 @@ +/* -*- c -*- */ +/* + * Copyright 2008 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 "sd.h" +#include "memory_map.h" +#include "stdint.h" +#include "stdio.h" + +static inline void +sd_packarg(unsigned char *argument,unsigned int value) +{ + argument[3] = (unsigned char)(value >> 24); + argument[2] = (unsigned char)(value >> 16); + argument[1] = (unsigned char)(value >> 8); + argument[0] = (unsigned char)(value); +} + +int +sd_init(void) +{ + unsigned char response[5]; + unsigned char argument[4]; + int i,j; + + for(i=0;i<4;i++) + argument[i] = 0; + + // Set clock to less than 400 kHz to start out + sdspi_regs->clkdiv = 128; + + // Delay at least 74 cycles + sd_assert_cs(); + for(i = 0; i < 100; i++) + sd_send_byte(SD_IDLE); + sd_deassert_cs(); + + // Initialization Sequence -- CMD0 CMD55 ACMD41 CMD58 + // Put card in idle state + if(sd_send_command(SD_CMD0,SD_CMD0_R,response,argument)==0) + return 0; // Something went wrong in command + + j = 0; + do { + j++; + if(sd_send_command(SD_CMD55,SD_CMD55_R,response,argument)==1) + sd_send_command(SD_ACMD41,SD_ACMD41_R,response,argument); + else + j = SD_IDLE_WAIT_MAX; + } + while(((response[0] & SD_MSK_IDLE) == SD_MSK_IDLE) && (j < SD_IDLE_WAIT_MAX)); + + if(j>= SD_IDLE_WAIT_MAX) // IDLE timeout exceeded, card asleep + return 0; + + // CMD58 reads the SD card capabilities + if(sd_send_command(SD_CMD58,SD_CMD58_R,response,argument)==0) + return 0; // CMD58 FAIL + + if((response[2] & SD_MSK_OCR_33) != SD_MSK_OCR_33) + return 0; // Card doesn't do 3.3V + + //printf("OCR = %x %x %x %x\n",response[0],response[1],response[2],response[3]); + + // Set blocklen here + sd_packarg(argument,SD_BLOCKLEN); + if(sd_send_command(SD_CMD16,SD_CMD16_R,response,argument)==0) + return 0; // Set Blocklen failed + + // Reset back to high speed + sdspi_regs->clkdiv = 4; + //puts("finished init\n"); + return 1; +} + +int sd_send_command(unsigned char cmd,unsigned char response_type, + unsigned char *response,unsigned char *argument) +{ + int i; + char response_length; + unsigned char tmp; + + sd_assert_cs(); + sd_send_byte((cmd & 0x3F) | 0x40); + for(i=3;i>=0;i--) + sd_send_byte(argument[i]); + sd_send_byte(SD_CRC); // Always the same + + response_length = 0; + switch(response_type) + { + case SD_R1: + case SD_R1B: + response_length = 1; + break; + case SD_R2: + response_length = 2; + break; + case SD_R3: + response_length = 5; + break; + default: + break; + } + + // Wait for a response, which will have a 0 start bit + i = 0; + do + { + tmp = sd_rcv_byte(); + i++; + } + while(((tmp & 0x80) != 0) && i < SD_CMD_TIMEOUT); + + if(i>= SD_CMD_TIMEOUT) + { + sd_deassert_cs(); + //puts("cmd send timeout\n"); + return 0; + } + + for(i=response_length-1; i>=0; i--) + { + response[i] = tmp; + tmp = sd_rcv_byte(); + } + i = 0; + if(response_type == SD_R1B) + { + do + { + i++; + tmp = sd_rcv_byte(); + } + while(tmp != SD_IDLE); + sd_send_byte(SD_IDLE); + } + + //puts("send cmd success\n"); + sd_deassert_cs(); + return 1; +} + +int +sd_read_block (unsigned int blockaddr, unsigned char *buf) +{ + unsigned char response[5]; + unsigned char argument[4]; + unsigned int i = 0; + unsigned char tmp; + + blockaddr <<= SD_BLOCKLEN_NBITS; + sd_packarg(argument,blockaddr); + if(sd_send_command(SD_CMD17,SD_CMD17_R,response,argument)==0) + return 0; //Failed READ; + if(response[0] != 0) + return 0; //Misaligned READ + + sd_assert_cs(); + i = 0; + do + { + tmp = sd_rcv_byte(); + i++; + } + while((tmp == 0xFF) && (i < SD_RD_TIMEOUT)); + if((i>= SD_RD_TIMEOUT) ||((tmp & SD_MSK_TOK_DATAERROR) == 0)) + { + sd_send_byte(SD_IDLE); // Send a dummy before quitting + return 0; // Data ERROR + } + for(i=0;i. + */ + +#ifndef INCLUDED_SD_H +#define INCLUDED_SD_H + +#include "memory_map.h" + +#define SD_READY 1 +#define SD_IDLE_WAIT_MAX 100 +#define SD_CMD_TIMEOUT 100 +#define SD_RD_TIMEOUT 1000 + +#define SD_CMD0 0 +#define SD_CMD1 1 +#define SD_CMD9 9 +#define SD_CMD10 10 +#define SD_CMD12 12 +#define SD_CMD13 13 +#define SD_CMD16 16 +#define SD_CMD17 17 +#define SD_CMD18 18 +#define SD_CMD24 24 +#define SD_CMD25 25 +#define SD_CMD27 27 +#define SD_CMD28 28 +#define SD_CMD29 29 +#define SD_CMD30 30 +#define SD_CMD32 32 +#define SD_CMD33 33 +#define SD_CMD38 38 +#define SD_CMD55 55 +#define SD_CMD58 58 +#define SD_CMD59 59 +#define SD_ACMD41 41 +#define SD_IDLE 0xFF +#define SD_CRC 0x95 + +#define SD_R1 1 +#define SD_R1B 2 +#define SD_R2 3 +#define SD_R3 4 + +#define SD_CMD0_R SD_R1 +#define SD_CMD16_R SD_R1 +#define SD_CMD17_R SD_R1 +#define SD_CMD55_R SD_R1 +#define SD_ACMD41_R SD_R1 +#define SD_CMD58_R SD_R3 + +#define SD_BLOCKLEN 512 +#define SD_BLOCKLEN_NBITS 9 + +#define SD_MSK_IDLE 0x01 +#define SD_MSK_OCR_33 0xC0 +#define SD_MSK_TOK_DATAERROR 0xE0 + + +int sd_init(void); + +static inline void +sd_assert_cs(void) +{ + // Wait for idle before doing anything + while(sdspi_regs->status != SD_READY) + ; + sdspi_regs->status = 1; +} + +static inline void +sd_deassert_cs(void) +{ + // Wait for idle before doing anything + while(sdspi_regs->status != SD_READY) + ; + sdspi_regs->status = 0; +} + +static inline char +sd_rcv_byte(void) +{ + // Wait for idle before doing anything + while(sdspi_regs->status != SD_READY) + ; + sdspi_regs->send_dat = SD_IDLE; + while(sdspi_regs->status != SD_READY) + ; + return sdspi_regs-> receive_dat; +} + +static inline void +sd_send_byte(char dat) +{ + // Wait for idle before doing anything + while(sdspi_regs->status != SD_READY) + ; // Wait for status = 1 (ready) + sdspi_regs->send_dat = dat; +} + + +int sd_send_command(unsigned char cmd,unsigned char response_type, + unsigned char *response,unsigned char *argument); + +int sd_read_block (unsigned int blockaddr, unsigned char *buf); +int sd_write_block(unsigned int blockaddr, const unsigned char *buf); + +#endif /* INCLUDED_SD_H */ diff --git a/firmware/microblaze/usrp2p/.gitignore b/firmware/microblaze/usrp2p/.gitignore new file mode 100644 index 000000000..18f715618 --- /dev/null +++ b/firmware/microblaze/usrp2p/.gitignore @@ -0,0 +1,9 @@ +/Makefile +/Makefile.in +/*.a +/*.bin +/*.dump +/*.ihx +/*.elf +/*.rom +/*.map diff --git a/firmware/microblaze/usrp2p/Makefile.am b/firmware/microblaze/usrp2p/Makefile.am new file mode 100644 index 000000000..eff544294 --- /dev/null +++ b/firmware/microblaze/usrp2p/Makefile.am @@ -0,0 +1,66 @@ +# +# 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 $(top_srcdir)/Makefile.common + +AM_CFLAGS = \ + $(COMMON_CFLAGS) + +AM_LDFLAGS = \ + $(COMMON_LFLAGS) \ + libusrp2p.a \ + -Wl,-defsym -Wl,_TEXT_START_ADDR=0x8050 \ + -Wl,-defsym -Wl,_STACK_SIZE=3072 + +#all of this here is to relocate the hardware vectors to somewhere normal. +COMMON_IHX_ARGS = \ + --change-section-address .vectors.sw_exception+0x8000 \ + --change-section-address .vectors.hw_exception+0x8000 \ + --change-section-address .vectors.interrupt+0x8000 \ + --change-section-address .vectors.reset+0x8000 +# $(MB_OBJCOPY) -O ihex $< $@ +# the below would work if objcopy weren't written by apes +# $(MB_OBJCOPY) -O ihex -w --change-section-address .vectors*+0x8000 $< $@ +# using the below will throw away the interrupt vectors when they get relocated below 0x0000. +# $(MB_OBJCOPY) -O ihex --change-addresses -0x8000 $< $@ + +######################################################################## +# USRP2P specific library and programs +######################################################################## +noinst_LIBRARIES = libusrp2p.a + +libusrp2p_a_SOURCES = \ + $(COMMON_SRCS) \ + clocks.c \ + spif.c \ + spi_flash.c \ + spi_flash_read.c \ + bootloader_utils.c + +noinst_PROGRAMS = \ + usrp2p_txrx_uhd.elf \ + usrp2p_blinkenlights.elf \ + usrp2p_uart_flash_loader.elf + +usrp2p_txrx_uhd_elf_SOURCES = \ + $(top_srcdir)/apps/txrx_uhd.c + +usrp2p_blinkenlights_elf_SOURCES = \ + $(top_srcdir)/apps/blinkenlights.c + +usrp2p_uart_flash_loader_elf_SOURCES = \ + $(top_srcdir)/apps/uart_flash_loader.c diff --git a/firmware/microblaze/usrp2p/bootconfig.h b/firmware/microblaze/usrp2p/bootconfig.h new file mode 100644 index 000000000..35c2726ed --- /dev/null +++ b/firmware/microblaze/usrp2p/bootconfig.h @@ -0,0 +1,61 @@ +/* -*- c -*- */ +/* + * Copyright 2009 Ettus Research LLC + * + * 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INCLUDED_BOOTCONFIG_H +#define INCLUDED_BOOTCONFIG_H + +#include + +typedef struct { + unsigned char fpga_image_number; + unsigned char firmware_image_number; +} bootconfig_t; + +static inline bootconfig_t +make_bootconfig(unsigned char fpga_image_number, unsigned char firmware_image_number) +{ + bootconfig_t r; + r.fpga_image_number = fpga_image_number; + r.firmware_image_number = firmware_image_number; + return r; +} + +void bootconfig_init(void); /* One time call to initialize */ + +/*! + * \return default boot configuration + */ +bootconfig_t bootconfig_get_default(void); + +/*! + * \brief Set the default boot configuration. + */ +bool bootconfig_set_default(bootconfig_t bc); + +/*! + * \brief attempt to boot the given fpga and software image. + * + * If successful, this routine does not return. + * If it fail for some reason, it returns. + */ +void bootconfig_boot(bootconfig_t bc); + +#endif /* INCLUDED_BOOTCONFIG_H */ diff --git a/firmware/microblaze/usrp2p/bootloader/.gitignore b/firmware/microblaze/usrp2p/bootloader/.gitignore new file mode 100644 index 000000000..17b0f82f3 --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/.gitignore @@ -0,0 +1,11 @@ +/*.ihx +/*.rmi +/*_rom +/*.elf +/*.bin +/*.dump +/*.log +/*.rom +/*.map +/Makefile +/Makefile.in diff --git a/firmware/microblaze/usrp2p/bootloader/Makefile.am b/firmware/microblaze/usrp2p/bootloader/Makefile.am new file mode 100644 index 000000000..1fc5daf9c --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/Makefile.am @@ -0,0 +1,39 @@ +# +# Copyright 2007,2008,2009 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, see . +# + +include $(top_srcdir)/Makefile.common + +ROM_LINKER_SCRIPT = u2p2-rom.ld + +# loads into 8K boot ram located at 0x0000_0000 +AM_CFLAGS = $(COMMON_CFLAGS) -I$(top_srcdir)/usrp2p +AM_LDFLAGS = -Wl,-T,$(ROM_LINKER_SCRIPT) $(COMMON_LFLAGS) -Wl,-defsym -Wl,_STACK_SIZE=1024 + +EXTRA_DIST = $(ROM_LINKER_SCRIPT) + +LDADD = $(top_srcdir)/usrp2p/libusrp2p.a + +noinst_PROGRAMS = \ + init_bootloader.elf + +init_bootloader_elf_SOURCES = init_bootloader.c + +.bin.rmi: + $(top_srcdir)/bin/bin_to_ram_macro_init.py $< $@ + +_generated_from_elf += \ + $(noinst_PROGRAMS:.elf=.rmi) diff --git a/firmware/microblaze/usrp2p/bootloader/fpga_bootloader.c b/firmware/microblaze/usrp2p/bootloader/fpga_bootloader.c new file mode 100644 index 000000000..9feff6ecd --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/fpga_bootloader.c @@ -0,0 +1,202 @@ +/* -*- c -*- */ +/* + * Copyright 2009 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 . + */ + +/* + * This code is bootloader f/w for the slot 0 fpga image. It's job is + * to figure out which fpga image should be loaded, and then to load + * that image from the SPI flash. (FIXME handle retries, errors, + * etc.) + * + * If the center button is down during boot, it loads firwmare + * from 0:0 instead of its normal action. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VERBOSE 1 + +#define OUR_FPGA_IMAGE_NUMBER 0 // this code only runs in slot 0 + +void hal_uart_init(void); +void spif_init(void); +void i2c_init(void); +void bootconfig_init(void); + +void pic_interrupt_handler() __attribute__ ((interrupt_handler)); + +void pic_interrupt_handler() +{ + // nop stub +} + +static int +flash_addr_of_fpga_slot(unsigned int fpga_slot) +{ + const struct flashdir *fd = get_flashdir(); + return fd->slot[fpga_slot + fd->fpga_slot0].start << spi_flash_log2_sector_size(); +} + + +/* + * If the first 256 bytes of the image contain the string of bytes, + * ff ff ff ff aa 99 55 66, we consider it a likely bitstream. + */ +static bool +looks_like_a_bitstream(unsigned int fpga_slot) +{ + unsigned char buf[256]; + static const unsigned char pattern[] = { + 0xff, 0xff, 0xff, 0xff, 0xaa, 0x99, 0x55, 0x66 + }; + + // Read the first 256 bytes of the bitstream + spi_flash_read(flash_addr_of_fpga_slot(fpga_slot), sizeof(buf), buf); + + for (int i = 0; i <= sizeof(buf) - sizeof(pattern); i++) + if (memcmp(pattern, &buf[i], sizeof(pattern)) == 0) + return true; + + return false; +} + +static bool +plausible_bootconfig(bootconfig_t bc) +{ + // Are the fields in range? + if (!validate_bootconfig(bc)) + return false; + + if (!looks_like_a_bitstream(map_fpga_image_number_to_fpga_slot(bc.fpga_image_number))) + return false; + + return true; +} + +// Attempt to boot the fpga image specified in next_boot +static void +initial_boot_attempt(eeprom_boot_info_t *ee) +{ + if (ee->next_boot.fpga_image_number == OUR_FPGA_IMAGE_NUMBER){ + load_firmware(); + return; + } + + ee->nattempts = 1; + _bc_write_eeprom_shadow(); + + unsigned int target_slot = + map_fpga_image_number_to_fpga_slot(ee->next_boot.fpga_image_number); + int flash_addr = flash_addr_of_fpga_slot(target_slot); + + putstr("fpga_bootloader: chaining to "); + puthex4(ee->next_boot.fpga_image_number); + putchar(':'); + puthex4(ee->next_boot.firmware_image_number); + newline(); + mdelay(100); + + while (1){ + icap_reload_fpga(flash_addr); + } +} + +int +main(int argc, char **argv) +{ + hal_disable_ints(); // In case we got here via jmp 0x0 + hal_uart_init(); + i2c_init(); + bootconfig_init(); // Must come after i2c_init. + spif_init(); // Needed for get_flashdir. + + sr_leds->leds = 0xAAAA; + + putstr("\n\n>>> fpga_bootloader <<<\n"); + + putstr("\nBOOTSTS "); + int bootsts = icap_read_config_reg(rBOOTSTS); + puthex32_nl(bootsts); + putstr("STAT "); + int stat = icap_read_config_reg(rSTAT); + puthex32_nl(stat); + + bool fallback = + ((bootsts & (BOOTSTS_VALID_0 | BOOTSTS_FALLBACK_0)) + == (BOOTSTS_VALID_0 | BOOTSTS_FALLBACK_0)); + + if (fallback){ + puts("FALLBACK_0 is set"); + // FIXME handle fallback condition. + } + + const struct flashdir *fd = get_flashdir(); + if (fd == 0) + abort(); + + eeprom_boot_info_t *ee = _bc_get_eeprom_shadow(); + + if (VERBOSE){ + putstr("nattempts: "); + puthex8_nl(ee->nattempts); + } + + mdelay(500); // wait for low-pass on switches + putstr("switches: "); puthex32_nl(readback->switches); + + bool center_btn_down = (readback->switches & BTN_CENTER) != 0; + if (center_btn_down){ + putstr("Center button is down!\n"); + // Force boot of image 0:0 + ee->next_boot = make_bootconfig(0, 0); + } + + // if next_boot is valid, try it + if (plausible_bootconfig(ee->next_boot)) + initial_boot_attempt(ee); // no return + + // if default_boot is valid, try it + if (plausible_bootconfig(ee->default_boot)){ + ee->next_boot = ee->default_boot; + initial_boot_attempt(ee); // no return + } + + // If we're here, we're in trouble. Try all of them... + for (int i = 0; i < 4; i++){ + bootconfig_t bc = make_bootconfig(i, 0); + if (plausible_bootconfig(bc)){ + ee->next_boot = bc; + initial_boot_attempt(ee); // no return + } + } + + // FIXME, try to find something we can load + puts("\n!!! Failed to find a valid FPGA bitstream!\n\n"); + + return 0; +} diff --git a/firmware/microblaze/usrp2p/bootloader/fw_bootloader.c b/firmware/microblaze/usrp2p/bootloader/fw_bootloader.c new file mode 100644 index 000000000..a2c32bf8e --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/fw_bootloader.c @@ -0,0 +1,50 @@ +/* -*- c -*- */ +/* + * Copyright 2009 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 +#include + + +void hal_uart_init(void); +void spif_init(void); +void i2c_init(void); +void bootconfig_init(void); + +void pic_interrupt_handler() __attribute__ ((interrupt_handler)); + +void pic_interrupt_handler() +{ + // nop stub +} + +int +main(int argc, char **argv) +{ + hal_disable_ints(); // In case we got here via jmp 0x0 + hal_uart_init(); + i2c_init(); + bootconfig_init(); // Must come after i2c_init. + spif_init(); // Needed for get_flashdir. + + load_firmware(); +} diff --git a/firmware/microblaze/usrp2p/bootloader/icap_test.c b/firmware/microblaze/usrp2p/bootloader/icap_test.c new file mode 100644 index 000000000..5feb9d014 --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/icap_test.c @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +#include +#include +#include +#include + +void delay(uint32_t t) { + while(t-- != 0) asm("NOP"); +} + + +int main(int argc, char *argv[]) { + pic_init(); + hal_uart_init(); + puts("\nStarting delay...\n"); + + output_regs->leds = 0xFF; + delay(4000000); + output_regs->leds = 0x00; + delay(4000000); + + puts("Rebooting FPGA to 0x00000000\n"); + icap_reload_fpga((uint32_t)0x00000000); + + return 0; +} diff --git a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c new file mode 100644 index 000000000..15d719d73 --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c @@ -0,0 +1,108 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include + +void pic_interrupt_handler() __attribute__ ((interrupt_handler)); + +void pic_interrupt_handler() +{ + // nop stub +} + +void load_ihex(void) { //simple IHEX parser to load proper records into RAM. loads program when it receives end of record. + char buf[128]; //input data buffer + uint8_t ihx[32]; //ihex data buffer + + ihex_record_t ihex_record; + ihex_record.data = ihx; + + while(1) { + gets(buf); + + if(!ihex_parse(buf, &ihex_record)) { //RAM data record is valid + if(ihex_record.addr >= RAM_BASE) { //it's expecting to see FULLY RELOCATED IHX RECORDS. every address referenced to 0x8000, including vectors. + memcpy((void *) (ihex_record.addr), ihex_record.data, ihex_record.length); + puts("OK"); + } else if(ihex_record.type == 1) { //end of record + puts("OK"); + //load main firmware + start_program(RAM_BASE); + puts("ERROR: main image returned! Back in IHEX load mode."); + } else puts("NOK"); //RAM loads do not support extended segment address records (04) -- upper 16 bits are always "0". + } else puts("NOK"); + } +} + +void delay(uint32_t t) { + while(t-- != 0) asm("NOP"); +} + +//let's clean up this logic. state machine? no, you only have to go through it once. + +//don't need else cases since all these are terminal cases + +int main(int argc, char *argv[]) { + hal_disable_ints(); // In case we got here via jmp 0x0 + output_regs->leds = 0xFF; + delay(500000); + output_regs->leds = 0x00; + hal_uart_init(); + spif_init(); +// i2c_init(); //for EEPROM + puts("USRP2+ bootloader\n"); + + if(BUTTON_PUSHED) { //see memory_map.h + puts("Starting USRP2+ in safe mode."); + if(is_valid_fw_image(SAFE_FW_IMAGE_LOCATION_ADDR)) { + spi_flash_read(SAFE_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE); + start_program(RAM_BASE); + puts("ERROR: return from main program! This should never happen!"); + //icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + } else { + puts("ERROR: no safe firmware image available. I am a brick. Feel free to load IHEX to RAM."); + load_ihex(); + } + } + + puts("Checking for valid production FPGA image..."); + if(is_valid_fpga_image(PROD_FPGA_IMAGE_LOCATION_ADDR)) { + puts("Valid production FPGA image found. Attempting to boot."); + //icap_reload_fpga(PROD_FPGA_IMAGE_LOCATION_ADDR); + } + puts("No valid production FPGA image found.\nAttempting to load production firmware..."); + if(is_valid_fw_image(PROD_FW_IMAGE_LOCATION_ADDR)) { + puts("Valid production firmware found. Loading..."); + spi_flash_read(PROD_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE); + start_program(RAM_BASE); + puts("ERROR: Return from main program! This should never happen!"); + //if this happens, though, the safest thing to do is reboot the whole FPGA and start over. + //icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + return 1; + } + puts("No valid production firmware found. Trying safe firmware..."); + if(is_valid_fw_image(SAFE_FW_IMAGE_LOCATION_ADDR)) { + spi_flash_read(SAFE_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE); + start_program(RAM_BASE); + puts("ERROR: return from main program! This should never happen!"); + //icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + return 1; //_exit will trap in loop + } + puts("ERROR: no safe firmware image available. I am a brick. Feel free to load IHEX to RAM."); + load_ihex(); + + return 0; +} diff --git a/firmware/microblaze/usrp2p/bootloader/serial_loader_burner.c b/firmware/microblaze/usrp2p/bootloader/serial_loader_burner.c new file mode 100644 index 000000000..4ac4df454 --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/serial_loader_burner.c @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 + +void hal_uart_init(void); +void spif_init(void); + +void pic_interrupt_handler() __attribute__ ((interrupt_handler)); + +void pic_interrupt_handler() +{ + // nop stub +} + +int +main(int argc, char **argv) +{ + hal_uart_init(); + spif_init(); + + sr_leds->leds = 0; + mdelay(100); + sr_leds->leds = ~0; + mdelay(100); + sr_leds->leds = 0; + + puts("\n\n>>> stage1: serial_loader_burner <<<"); + + gdbstub2_main_loop(); +} diff --git a/firmware/microblaze/usrp2p/bootloader/spi_bootloader.c b/firmware/microblaze/usrp2p/bootloader/spi_bootloader.c new file mode 100644 index 000000000..678e66cf7 --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/spi_bootloader.c @@ -0,0 +1,134 @@ +/* -*- c -*- */ +/* + * Copyright 2009 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 +#include + + +void hal_uart_init(void); +void spif_init(void); + +void pic_interrupt_handler() __attribute__ ((interrupt_handler)); + +void pic_interrupt_handler() +{ + // nop stub +} + +static void +error(int e) +{ + putstr("ERR"); + puthex8(e); + newline(); +} + +static void +load(uint32_t flash_addr, uint32_t ram_addr, uint32_t size) +{ + spi_flash_read(flash_addr, size, (void *) ram_addr); +} + +static bool +load_from_slot(const struct flashdir *fd, int fw_slot) +{ + putstr("Loading f/w image "); + putchar('0' + fw_slot); + putstr("... "); + + if (fw_slot >= fd->fw_nslots){ + error(1); + return false; + } + + int slot = fw_slot + fd->fw_slot0; + if (fd->slot[slot].start == 0 || fd->slot[slot].start == 0xffff + || fd->slot[slot].len == 0 || fd->slot[slot].len == 0xffff){ + error(2); + return false; + } + + uint32_t sbf_base = fd->slot[slot].start << spi_flash_log2_sector_size(); + uint32_t sbf_len = fd->slot[slot].len << spi_flash_log2_sector_size(); + uint32_t sbf_offset = 0; + + struct sbf_header sbf; + spi_flash_read(sbf_base, sizeof(struct sbf_header), &sbf); + if (sbf.magic != SBF_MAGIC || sbf.nsections > SBF_MAX_SECTIONS){ + error(3); + return false; + } + sbf_offset += sizeof(struct sbf_header); + + unsigned int i; + for (i = 0; i < sbf.nsections; i++){ + if (sbf_offset + sbf.sec_desc[i].length > sbf_len){ + error(4); + return false; + } + load(sbf_offset + sbf_base, + sbf.sec_desc[i].target_addr, + sbf.sec_desc[i].length); + sbf_offset += sbf.sec_desc[i].length; + } + putstr("Done!"); + + typedef void (*fptr_t)(void); + (*(fptr_t) sbf.entry)(); // almost certainly no return + + return true; +} + +int +main(int argc, char **argv) +{ + hal_uart_init(); + spif_init(); + + sr_leds->leds = 0; + mdelay(100); + sr_leds->leds = ~0; + mdelay(100); + sr_leds->leds = 0; + + putstr("\n>>> spi_bootloader <<<\n"); + + const struct flashdir *fd = get_flashdir(); + if (fd == 0) + abort(); + + while(1){ + int sw; + int fw_slot; + + sw = readback->switches; + fw_slot = sw & 0x7; + + if (!load_from_slot(fd, fw_slot)){ + if (fw_slot != 0){ + putstr("Falling back to slot 0\n"); + load_from_slot(fd, 0); + } + } + } +} diff --git a/firmware/microblaze/usrp2p/bootloader/u2p2-rom.ld b/firmware/microblaze/usrp2p/bootloader/u2p2-rom.ld new file mode 100644 index 000000000..4c9eaa8e5 --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader/u2p2-rom.ld @@ -0,0 +1,190 @@ +/* + * Same as default, but with bss and stack moved to top 2K of main ram + * Copied from qr-rom.ld + */ + +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-microblaze", "", "") +/*SEARCH_DIR("/home/eb/build/Xilinx_EDK_GNU_10.1i/mb/release/lin/mb/microblaze-xilinx-elf/lib");*/ + + +ENTRY(_start) +_TEXT_START_ADDR = DEFINED(_TEXT_START_ADDR) ? _TEXT_START_ADDR : 0x50; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x0; +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x400; +_BSS_START_ADDR = DEFINED(_BSS_START_ADDR) ? _BSS_START_ADDR : 0xF800; +SECTIONS +{ + .vectors.reset 0x0 : { KEEP (*(.vectors.reset)) } = 0 + .vectors.sw_exception 0x8 : { KEEP (*(.vectors.sw_exception)) } = 0 + .vectors.interrupt 0x10 : { KEEP (*(.vectors.interrupt)) } = 0 + .vectors.debug_sw_break 0x18 : { KEEP (*(.vectors.debug_sw_break)) } = 0 + .vectors.hw_exception 0x20 : { KEEP (*(.vectors.hw_exception)) } = 0 + . = _TEXT_START_ADDR; + _ftext = .; + .text : { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + _etext = .; + .init : { KEEP (*(.init)) } =0 + .fini : { KEEP (*(.fini)) } =0 + PROVIDE (__CTOR_LIST__ = .); + PROVIDE (___CTOR_LIST__ = .); + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + PROVIDE (__CTOR_END__ = .); + PROVIDE (___CTOR_END__ = .); + PROVIDE (__DTOR_LIST__ = .); + PROVIDE (___DTOR_LIST__ = .); + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + PROVIDE (__DTOR_END__ = .); + PROVIDE (___DTOR_END__ = .); + . = ALIGN(4); + _frodata = . ; + .rodata : { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + CONSTRUCTORS; /* Is this needed? */ + } + _erodata = .; + /* Alignments by 8 to ensure that _SDA2_BASE_ on a word boundary */ + /* Note that .sdata2 and .sbss2 must be contiguous */ + . = ALIGN(8); + _ssrw = .; + .sdata2 : { + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + } + . = ALIGN(4); + .sbss2 : { + PROVIDE (__sbss2_start = .); + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + PROVIDE (__sbss2_end = .); + } + . = ALIGN(8); + _essrw = .; + _ssrw_size = _essrw - _ssrw; + PROVIDE (_SDA2_BASE_ = _ssrw + (_ssrw_size / 2 )); + . = ALIGN(4); + _fdata = .; + .data : { + *(.data) + *(.gnu.linkonce.d.*) + CONSTRUCTORS; /* Is this needed? */ + } + _edata = . ; + /* Added to handle pic code */ + .got : { + *(.got) + } + .got1 : { + *(.got1) + } + .got2 : { + *(.got2) + } + /* Added by Sathya to handle C++ exceptions */ + .eh_frame : { + *(.eh_frame) + } + .jcr : { + *(.jcr) + } + .gcc_except_table : { + *(.gcc_except_table) + } + /* Alignments by 8 to ensure that _SDA_BASE_ on a word boundary */ + /* Note that .sdata and .sbss must be contiguous */ + . = ALIGN(8); + _ssro = .; + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + } + . = ALIGN(4); + .sbss : { + PROVIDE (__sbss_start = .); + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + PROVIDE (__sbss_end = .); + } + . = ALIGN(8); + _essro = .; + _ssro_size = _essro - _ssro; + PROVIDE (_SDA_BASE_ = _ssro + (_ssro_size / 2 )); + . = _BSS_START_ADDR; + . = ALIGN(4); + _fbss = .; + .bss : { + PROVIDE (__bss_start = .); + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + PROVIDE (__bss_end = .); + } + . = ALIGN(4); + .heap : { + _heap = .; + _heap_start = .; + . += _HEAP_SIZE; + _heap_end = .; + } + _end = .; + . = ALIGN(4); + . = 0xFFF0; + .stack : { + /* + _stack_end = .; + . += _STACK_SIZE; + . = ALIGN(8); + _stack = .; + _end = .; + */ + _stack_end = .; + _stack = .; + } + .tdata : { + *(.tdata) + *(.tdata.*) + *(.gnu.linkonce.td.*) + } + .tbss : { + *(.tbss) + *(.tbss.*) + *(.gnu.linkonce.tb.*) + } +} diff --git a/firmware/microblaze/usrp2p/bootloader_utils.c b/firmware/microblaze/usrp2p/bootloader_utils.c new file mode 100644 index 000000000..00893db02 --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader_utils.c @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +//contains routines for loading programs from Flash. depends on Flash libraries. +#include +#include +#include + + +int is_valid_fpga_image(uint32_t addr) { + static const uint8_t fpgaheader[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x99}; //AA 99 is the standard Xilinx sync sequence, and it's always prefixed with 0xFF padding + uint8_t buf[10]; + spi_flash_read(addr, 6, buf); + return memcmp(buf, fpgaheader, 6) == 0; +} + +int is_valid_fw_image(uint32_t addr) { + static const uint8_t fwheader[] = {0xB0, 0x00, 0x00, 0x00, 0xB8, 0x08}; //just lookin for a jump to anywhere located at the reset vector + uint8_t buf[12]; + spi_flash_read(addr, 6, buf); + return memcmp(buf, fwheader, 6) == 0; +} + +void start_program(uint32_t addr) +{ + memcpy(0x00000000, addr+0x00000000, 36); //copy the whole vector table, with the reset vector, into boot RAM + typedef void (*fptr_t)(void); + (*(fptr_t) 0x00000000)(); // most likely no return +} + diff --git a/firmware/microblaze/usrp2p/bootloader_utils.h b/firmware/microblaze/usrp2p/bootloader_utils.h new file mode 100644 index 000000000..c72128f43 --- /dev/null +++ b/firmware/microblaze/usrp2p/bootloader_utils.h @@ -0,0 +1,21 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Ettus Research LLC + * + */ + +#include + +//we're working in bytes and byte addresses so we can run the same code with Flash chips of different sector sizes. +#define FPGA_IMAGE_SIZE_BYTES 2097152 +//instead of 32K, we write 31K because we're using the top 1K for stack space! +#define FW_IMAGE_SIZE_BYTES 31744 + +#define SAFE_FPGA_IMAGE_LOCATION_ADDR 0x00000000 +#define SAFE_FW_IMAGE_LOCATION_ADDR 0x007F0000 +#define PROD_FPGA_IMAGE_LOCATION_ADDR 0x00200000 +#define PROD_FW_IMAGE_LOCATION_ADDR 0x00400000 + +int is_valid_fpga_image(uint32_t addr); +int is_valid_fw_image(uint32_t addr); +void start_program(uint32_t addr); diff --git a/firmware/microblaze/usrp2p/clocks.c b/firmware/microblaze/usrp2p/clocks.c new file mode 100644 index 000000000..3488ec468 --- /dev/null +++ b/firmware/microblaze/usrp2p/clocks.c @@ -0,0 +1,259 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include "memory_map.h" +#include "ad9510.h" +#include "spi.h" +#include "u2_init.h" +#include "nonstdio.h" + +//USRP2PLUS clocks: +//Clock 0: testclk +//Clock 1: FPGA clk +//Clock 2: ADC clk +//Clock 3: DAC clk +//Clock 4: SER clk +//Clock 5: TX dboard clk +//Clock 6: EXP clk +//Clock 7: RX dboard clk + +//TODO: should have enough brains to init the FPGA clock for USRP2+. all others are suspect. +//note that without EEPROM support u2_hw_rev_major is going to be incorrect. + +void +clocks_init(void) +{ + // Set up basic clocking functions in AD9510 + ad9510_write_reg(0x45, 0x01); // CLK2 drives distribution + + clocks_enable_fpga_clk(true, 1); + + spi_wait(); + + // Set up PLL for 10 MHz reference + // Reg 4, A counter, Don't Care + ad9510_write_reg(0x05, 0x00); // Reg 5, B counter MSBs, 0 + ad9510_write_reg(0x06, 0x05); // Reg 6, B counter LSBs, 5 + // Reg 7, Loss of reference detect, doesn't work yet, 0 + ad9510_write_reg(0x5A, 0x01); // Update Regs + + // Primary clock configuration + clocks_mimo_config(MC_WE_DONT_LOCK); + + // Set up other clocks + //clocks_enable_test_clk(false, 0); + //clocks_enable_tx_dboard(false, 0); + //clocks_enable_rx_dboard(false, 0); + clocks_enable_eth_phyclk(false, 0); //PHY clk is separate now (u2r4, u2p) + + // Enable clock to ADCs and DACs + //clocks_enable_dac_clk(true, 1); + //clocks_enable_adc_clk(true, 1); +} + + +void +clocks_mimo_config(int flags) +{ + if (flags & _MC_WE_LOCK){ + // Reg 8, Charge pump on, dig lock det, positive PFD, 47 + ad9510_write_reg(0x08, 0x47); + } + else { + // Reg 8, Charge pump off, dig lock det, positive PFD + ad9510_write_reg(0x08, 0x00); + } + + // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA + ad9510_write_reg(0x09, 0x00); + // Reg A, Prescaler of 2, everything normal 04 + ad9510_write_reg(0x0A, 0x04); + // Reg B, R Div MSBs, 0 + ad9510_write_reg(0x0B, 0x00); + // Reg C, R Div LSBs, 1 + ad9510_write_reg(0x0C, 0x01); + // Reg D, Antibacklash, Digital lock det, 0 + + ad9510_write_reg(0x5A, 0x01); // Update Regs + + spi_wait(); + + // Allow for clock switchover + + if (flags & _MC_WE_LOCK){ // WE LOCK + if (flags & _MC_MIMO_CLK_INPUT) { + // Turn on ref output and choose the MIMO connector + output_regs->clk_ctrl = 0x15; + } + else { + // turn on ref output and choose the SMA + output_regs->clk_ctrl = 0x1C; + } + } + else { // WE DONT LOCK + // Disable both ext clk inputs + output_regs->clk_ctrl = 0x10; + } + + // Do we drive a clock onto the MIMO connector? + if (flags & MC_PROVIDE_CLK_TO_MIMO) + clocks_enable_clkexp_out(true,10); + else + clocks_enable_clkexp_out(false,0); +} + +bool +clocks_lock_detect() +{ + if(pic_regs->pending & PIC_CLKSTATUS) + return true; + return false; +} + +int inline +clocks_gen_div(int divisor) +{ + int L,H; + L = (divisor>>1)-1; + H = divisor-L-2; + return (L<<4)|H; +} + +#define CLOCK_OUT_EN 0x08 +#define CLOCK_OUT_DIS_CMOS 0x01 +#define CLOCK_OUT_DIS_PECL 0x02 +#define CLOCK_DIV_DIS 0x80 +#define CLOCK_DIV_EN 0x00 + +#define CLOCK_MODE_PECL 1 +#define CLOCK_MODE_LVDS 2 +#define CLOCK_MODE_CMOS 3 + +//CHANGED: set to PECL for default behavior +void +clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mode) +{ + int enable_word, div_word, div_en_word; + + switch(mode) { + case CLOCK_MODE_LVDS : + enable_word = enable ? 0x02 : 0x03; + break; + case CLOCK_MODE_CMOS : + enable_word = enable ? 0x08 : 0x09; + break; + case CLOCK_MODE_PECL : + default: + enable_word = enable ? 0x08 : 0x0A; + break; + } + if(enable && (divisor>1)) { + div_word = clocks_gen_div(divisor); + div_en_word = CLOCK_DIV_EN; + } + else { + div_word = 0; + div_en_word = CLOCK_DIV_DIS; + } + + ad9510_write_reg(reg_en,enable_word); // Output en/dis + ad9510_write_reg(reg_div,div_word); // Set divisor + ad9510_write_reg(reg_div+1,div_en_word); // Enable or Bypass Divider + ad9510_write_reg(0x5A, 0x01); // Update Regs +} + +// Clock 0 +/*void +clocks_enable_test_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL); +}*/ + +// Clock 1 +void +clocks_enable_fpga_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL); +} + +// Clock 2 on Rev 3, Clock 5 on Rev 4, Clock 6 on USRP2+ +void +clocks_enable_clkexp_out(bool enable, int divisor) +{ + if(u2_hw_rev_major == 3) + clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); + else if(u2_hw_rev_major == 4) { + ad9510_write_reg(0x34,0x00); // Turn on fine delay + ad9510_write_reg(0x35,0x00); // Set Full Scale to nearly 10ns + ad9510_write_reg(0x36,0x1c); // Set fine delay. 0x20 is midscale + clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); + } + else if(u2_hw_rev_major == 10) { + ad9510_write_reg(0x34, 0x00); + ad9510_write_reg(0x35, 0x00); + ad9510_write_reg(0x36, 0x1C); + clocks_enable_XXX_clk(enable, divisor, 0x42, 0x52, CLOCK_MODE_LVDS); + } + else + putstr("ERR (clocks_enable_clkexp_out): Invalid hw rev, don't know what to do!\n"); +} + +// Clock 5 on Rev 3, none (was 2) on Rev 4, none on USRP2+ +void +clocks_enable_eth_phyclk(bool enable, int divisor) +{ + if(u2_hw_rev_major == 3) + clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); + else if(u2_hw_rev_major == 4) + clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); + else + putstr("(clocks_enable_eth_phyclk): no eth PHY clock or invalid hw rev\n"); //not really an error +} + +// Clock 3 +/*void +clocks_enable_dac_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL); +}*/ + +// Clock 4 +/*void +clocks_enable_adc_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS); +}*/ + +// Clock 6 +/*void +clocks_enable_tx_dboard(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS); +}*/ + +// Clock 7 +/*void +clocks_enable_rx_dboard(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS); +}*/ diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h new file mode 100644 index 000000000..fc0094e67 --- /dev/null +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -0,0 +1,838 @@ +/* -*- c -*- */ +/* + * Copyright 2007,2008,2009 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, see . + */ + +/* Overall Memory Map + * 0000-FFFF 64K RAM space + * + * 0000-1FFF 8K Boot RAM + * 2000-5FFF 16K Buffer pool + * 6000-7FFF 8K Peripherals + * 8000-FFFF 32K Main System RAM + + +From u2plus_core.v: +wb_1master #(.decode_w(8), +.s0_addr(8'b0000_0000),.s0_mask(8'b1110_0000), // 0-8K, Boot RAM +.s1_addr(8'b0100_0000),.s1_mask(8'b1100_0000), // 16K-32K, Buffer Pool +.s2_addr(8'b0011_0000),.s2_mask(8'b1111_1111), // SPI 0x3000 +.s3_addr(8'b0011_0001),.s3_mask(8'b1111_1111), // I2C 0x3100 +.s4_addr(8'b0011_0010),.s4_mask(8'b1111_1111), // GPIO 0x3200 +.s5_addr(8'b0011_0011),.s5_mask(8'b1111_1111), // Readback 0x3300 +.s6_addr(8'b0011_0100),.s6_mask(8'b1111_1111), // Ethernet MAC 0x3400 +.s7_addr(8'b0010_0000),.s7_mask(8'b1111_0000), // 8-12K, Settings Bus (only uses 1K) 0x2000-0x2FFF +.s8_addr(8'b0011_0101),.s8_mask(8'b1111_1111), // PIC 0x3500 +.s9_addr(8'b0011_0110),.s9_mask(8'b1111_1111), // Unused 0x3600 +.sa_addr(8'b0011_0111),.sa_mask(8'b1111_1111), // UART 0x3700 +.sb_addr(8'b0011_1000),.sb_mask(8'b1111_1111), // ATR 0x3800 +.sc_addr(8'b0011_1001),.sc_mask(8'b1111_1111), // Unused 0x3900 +.sd_addr(8'b0011_1010),.sd_mask(8'b1111_1111), // ICAP 0x3A00 +.se_addr(8'b0011_1011),.se_mask(8'b1111_1111), // SPI Flash 0x3B00 +.sf_addr(8'b1000_0000),.sf_mask(8'b1000_0000), // 32-64K, Main RAM 0x8000-0xFFFF + .dw(dw),.aw(aw),.sw(sw)) wb_1master + + */ + + +#ifndef INCLUDED_MEMORY_MAP_H +#define INCLUDED_MEMORY_MAP_H + +#include + + +#define MASTER_CLK_RATE 100000000 // 100 MHz + + +//////////////////////////////////////////////////////////////// +// +// Memory map for embedded wishbone bus +// +//////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////// +// Boot RAM, Slave 0 + +#define BOOTRAM_BASE 0x0000 + + +//////////////////////////////////////////////////////////////// +// Buffer Pool RAM, Slave 1 +// +// The buffers themselves are located in Slave 1, Buffer Pool RAM. +// The status registers are in Slave 5, Buffer Pool Status. +// The control register is in Slave 7, Settings Bus. + +#define BUFFER_POOL_RAM_BASE 0x4000 + +#define NBUFFERS 8 +#define BP_NLINES 0x0200 // number of 32-bit lines in a buffer +#define BP_LAST_LINE (BP_NLINES - 1) // last line in a buffer + +#define buffer_pool_ram \ + ((uint32_t *) BUFFER_POOL_RAM_BASE) + +#define buffer_ram(n) (&buffer_pool_ram[(n) * BP_NLINES]) + + +///////////////////////////////////////////////////// +// SPI Core, Slave 2. See core docs for more info +#define SPI_BASE 0x3000 // Base address (16-bit) is base peripheral addr + +typedef struct { + volatile uint32_t txrx0; + volatile uint32_t txrx1; + volatile uint32_t txrx2; + volatile uint32_t txrx3; + volatile uint32_t ctrl; + volatile uint32_t div; + volatile uint32_t ss; +} spi_regs_t; + +#define spi_regs ((spi_regs_t *) SPI_BASE) + + +// Masks for controlling different peripherals +#define SPI_SS_AD9510 1 +#define SPI_SS_AD9777 2 +#define SPI_SS_RX_DAC 4 +#define SPI_SS_RX_ADC 8 +#define SPI_SS_RX_DB 16 +#define SPI_SS_TX_DAC 32 +#define SPI_SS_TX_ADC 64 +#define SPI_SS_TX_DB 128 +#define SPI_SS_ADS62P44 256 + +// Masks for different parts of CTRL reg +#define SPI_CTRL_ASS (1<<13) +#define SPI_CTRL_IE (1<<12) +#define SPI_CTRL_LSB (1<<11) +#define SPI_CTRL_TXNEG (1<<10) +#define SPI_CTRL_RXNEG (1<< 9) +#define SPI_CTRL_GO_BSY (1<< 8) +#define SPI_CTRL_CHAR_LEN_MASK 0x7F + +//////////////////////////////////////////////// +// I2C, Slave 3 +// See Wishbone I2C-Master Core Specification. + +#define I2C_BASE 0x3100 + +typedef struct { + volatile uint32_t prescaler_lo; // r/w + volatile uint32_t prescaler_hi; // r/w + volatile uint32_t ctrl; // r/w + volatile uint32_t data; // wr = transmit reg; rd = receive reg + volatile uint32_t cmd_status; // wr = command reg; rd = status reg +} i2c_regs_t; + +#define i2c_regs ((i2c_regs_t *) I2C_BASE) + +#define I2C_CTRL_EN (1 << 7) // core enable +#define I2C_CTRL_IE (1 << 6) // interrupt enable + +// +// STA, STO, RD, WR, and IACK bits are cleared automatically +// +#define I2C_CMD_START (1 << 7) // generate (repeated) start condition +#define I2C_CMD_STOP (1 << 6) // generate stop condition +#define I2C_CMD_RD (1 << 5) // read from slave +#define I2C_CMD_WR (1 << 4) // write to slave +#define I2C_CMD_NACK (1 << 3) // when a rcvr, send ACK (ACK=0) or NACK (ACK=1) +#define I2C_CMD_RSVD_2 (1 << 2) // reserved +#define I2C_CMD_RSVD_1 (1 << 1) // reserved +#define I2C_CMD_IACK (1 << 0) // set to clear pending interrupt + +#define I2C_ST_RXACK (1 << 7) // Received acknowledgement from slave (1 = NAK, 0 = ACK) +#define I2C_ST_BUSY (1 << 6) // 1 after START signal detected; 0 after STOP signal detected +#define I2C_ST_AL (1 << 5) // Arbitration lost. 1 when core lost arbitration +#define I2C_ST_RSVD_4 (1 << 4) // reserved +#define I2C_ST_RSVD_3 (1 << 3) // reserved +#define I2C_ST_RSVD_2 (1 << 2) // reserved +#define I2C_ST_TIP (1 << 1) // Transfer-in-progress +#define I2C_ST_IP (1 << 0) // Interrupt pending + + +//////////////////////////////////////////////// +// GPIO, Slave 4 +// +// These go to the daughterboard i/o pins + +#define GPIO_BASE 0x3200 + +typedef struct { + volatile uint32_t io; // tx data in high 16, rx in low 16 + volatile uint32_t ddr; // 32 bits, 1 means output. tx in high 16, rx in low 16 + volatile uint32_t tx_sel; // 16 2-bit fields select which source goes to TX DB + volatile uint32_t rx_sel; // 16 2-bit fields select which source goes to RX DB +} gpio_regs_t; + +// each 2-bit sel field is layed out this way +#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg +#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic +#define GPIO_SEL_DEBUG_0 2 // if pin is an output, debug lines from FPGA fabric +#define GPIO_SEL_DEBUG_1 3 // if pin is an output, debug lines from FPGA fabric + +#define gpio_base ((gpio_regs_t *) GPIO_BASE) + +/////////////////////////////////////////////////// +// Buffer Pool Status, Slave 5 +// +// The buffers themselves are located in Slave 1, Buffer Pool RAM. +// The status registers are in Slave 5, Buffer Pool Status. +// The control register is in Slave 7, Settings Bus. + +#define BUFFER_POOL_STATUS_BASE 0x3300 + +typedef struct { + volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer + volatile uint32_t status; // error and done flags + volatile uint32_t hw_config; // see below + volatile uint32_t dummy[3]; + volatile uint32_t irqs; + volatile uint32_t pri_enc_bp_status; + volatile uint32_t cycle_count; +} buffer_pool_status_t; + +#define buffer_pool_status ((buffer_pool_status_t *) BUFFER_POOL_STATUS_BASE) + +#define BUTTON_PUSHED ((buffer_pool_status->irqs & PIC_BUTTON) ? 0 : 1) + +/* + * Buffer n's xfer is done. + * Clear this bit by issuing bp_clear_buf(n) + */ +#define BPS_DONE(n) (0x00000001 << (n)) +#define BPS_DONE_0 BPS_DONE(0) +#define BPS_DONE_1 BPS_DONE(1) +#define BPS_DONE_2 BPS_DONE(2) +#define BPS_DONE_3 BPS_DONE(3) +#define BPS_DONE_4 BPS_DONE(4) +#define BPS_DONE_5 BPS_DONE(5) +#define BPS_DONE_6 BPS_DONE(6) +#define BPS_DONE_7 BPS_DONE(7) + +/* + * Buffer n's xfer had an error. + * Clear this bit by issuing bp_clear_buf(n) + */ +#define BPS_ERROR(n) (0x00000100 << (n)) +#define BPS_ERROR_0 BPS_ERROR(0) +#define BPS_ERROR_1 BPS_ERROR(1) +#define BPS_ERROR_2 BPS_ERROR(2) +#define BPS_ERROR_3 BPS_ERROR(3) +#define BPS_ERROR_4 BPS_ERROR(4) +#define BPS_ERROR_5 BPS_ERROR(5) +#define BPS_ERROR_6 BPS_ERROR(6) +#define BPS_ERROR_7 BPS_ERROR(7) + +/* + * Buffer n is idle. A buffer is idle if it's not + * DONE, ERROR, or processing a transaction. If it's + * IDLE, it's safe to start a new transaction. + * + * Clear this bit by starting a xfer with + * bp_send_from_buf or bp_receive_to_buf. + */ +#define BPS_IDLE(n) (0x00010000 << (n)) +#define BPS_IDLE_0 BPS_IDLE(0) +#define BPS_IDLE_1 BPS_IDLE(1) +#define BPS_IDLE_2 BPS_IDLE(2) +#define BPS_IDLE_3 BPS_IDLE(3) +#define BPS_IDLE_4 BPS_IDLE(4) +#define BPS_IDLE_5 BPS_IDLE(5) +#define BPS_IDLE_6 BPS_IDLE(6) +#define BPS_IDLE_7 BPS_IDLE(7) + +/* + * Buffer n has a "slow path" packet in it. + * This bit is orthogonal to the bits above and indicates that + * the FPGA ethernet rx protocol engine has identified this packet + * as one requiring firmware intervention. + */ +#define BPS_SLOWPATH(n) (0x01000000 << (n)) +#define BPS_SLOWPATH_0 BPS_SLOWPATH(0) +#define BPS_SLOWPATH_1 BPS_SLOWPATH(1) +#define BPS_SLOWPATH_2 BPS_SLOWPATH(2) +#define BPS_SLOWPATH_3 BPS_SLOWPATH(3) +#define BPS_SLOWPATH_4 BPS_SLOWPATH(4) +#define BPS_SLOWPATH_5 BPS_SLOWPATH(5) +#define BPS_SLOWPATH_6 BPS_SLOWPATH(6) +#define BPS_SLOWPATH_7 BPS_SLOWPATH(7) + + +#define BPS_DONE_ALL 0x000000ff // mask of all dones +#define BPS_ERROR_ALL 0x0000ff00 // mask of all errors +#define BPS_IDLE_ALL 0x00ff0000 // mask of all idles +#define BPS_SLOWPATH_ALL 0xff000000 // mask of all slowpaths + +// The hw_config register + +#define HWC_SIMULATION 0x80000000 +#define HWC_WB_CLK_DIV_MASK 0x0000000f + +/*! + * \brief return non-zero if we're running under the simulator + */ +inline static int +hwconfig_simulation_p(void) +{ + return buffer_pool_status->hw_config & HWC_SIMULATION; +} + +/*! + * \brief Return Wishbone Clock divisor. + * The processor runs at the Wishbone Clock rate which is MASTER_CLK_RATE / divisor. + */ +inline static int +hwconfig_wishbone_divisor(void) +{ + return buffer_pool_status->hw_config & HWC_WB_CLK_DIV_MASK; +} + +/////////////////////////////////////////////////// +// Ethernet Core, Slave 6 + +#define ETH_BASE 0x3400 + +#include "eth_mac_regs.h" + +#define eth_mac ((eth_mac_regs_t *) ETH_BASE) + +//////////////////////////////////////////////////// +// Settings Bus, Slave #7, Not Byte Addressable! +// +// Output-only from processor point-of-view. +// 1KB of address space (== 256 32-bit write-only regs) + + +#define MISC_OUTPUT_BASE 0x2000 +#define TX_PROTOCOL_ENGINE_BASE 0x2080 +#define RX_PROTOCOL_ENGINE_BASE 0x20C0 +#define BUFFER_POOL_CTRL_BASE 0x2100 +#define LAST_SETTING_REG 0x23FC // last valid setting register + +#define SR_MISC 0 +#define SR_TX_PROT_ENG 32 +#define SR_RX_PROT_ENG 48 +#define SR_BUFFER_POOL_CTRL 64 +#define SR_UDP_SM 96 +#define SR_TX_DSP 208 +#define SR_TX_CTRL 224 +#define SR_RX_DSP 160 +#define SR_RX_CTRL 176 +#define SR_TIME64 192 +#define SR_SIMTIMER 198 +#define SR_LAST 255 + +#define _SR_ADDR(sr) (MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t)) + +// --- buffer pool control regs --- + +typedef struct { + volatile uint32_t ctrl; +} buffer_pool_ctrl_t; + +// buffer pool ports + +#define PORT_SERDES 0 // serial/deserializer +#define PORT_DSP 1 // DSP tx or rx pipeline +#define PORT_ETH 2 // ethernet tx or rx +#define PORT_RAM 3 // RAM tx or rx + +// the buffer pool ctrl register fields + +#define BPC_BUFFER(n) (((n) & 0xf) << 28) +#define BPC_BUFFER_MASK BPC_BUFFER(~0) +#define BPC_BUFFER_0 BPC_BUFFER(0) +#define BPC_BUFFER_1 BPC_BUFFER(1) +#define BPC_BUFFER_2 BPC_BUFFER(2) +#define BPC_BUFFER_3 BPC_BUFFER(3) +#define BPC_BUFFER_4 BPC_BUFFER(4) +#define BPC_BUFFER_5 BPC_BUFFER(5) +#define BPC_BUFFER_6 BPC_BUFFER(6) +#define BPC_BUFFER_7 BPC_BUFFER(7) +#define BPC_BUFFER_NIL BPC_BUFFER(0x8) // disable + +#define BPC_PORT(n) (((n) & 0x7) << 25) +#define BPC_PORT_MASK BPC_PORT(~0) +#define BPC_PORT_SERDES BPC_PORT(PORT_SERDES) +#define BPC_PORT_DSP BPC_PORT(PORT_DSP) +#define BPC_PORT_ETH BPC_PORT(PORT_ETH) +#define BPC_PORT_RAM BPC_PORT(PORT_RAM) +#define BPC_PORT_NIL BPC_PORT(0x4) // disable + +#define BPC_CLR (1 << 24) // mutually excl commands +#define BPC_READ (1 << 23) +#define BPC_WRITE (1 << 22) + +#define BPC_STEP(step) (((step) & 0xf) << 18) +#define BPC_STEP_MASK BPC_STEP(~0) +#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9) +#define BPC_LAST_LINE_MASK BPC_LAST_LINE(~0) +#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0) +#define BPC_FIRST_LINE_MASK BPC_FIRST_LINE(~0) + +#define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE) + +// --- misc outputs --- + +typedef struct { + volatile uint32_t clk_ctrl; + volatile uint32_t serdes_ctrl; + volatile uint32_t adc_ctrl; + volatile uint32_t leds; + volatile uint32_t phy_ctrl; // LSB is reset line to eth phy + volatile uint32_t debug_mux_ctrl; + volatile uint32_t ram_page; // FIXME should go somewhere else... + volatile uint32_t flush_icache; // Flush the icache + volatile uint32_t led_src; // HW or SW control for LEDs +} output_regs_t; + +#define SERDES_ENABLE 8 +#define SERDES_PRBSEN 4 +#define SERDES_LOOPEN 2 +#define SERDES_RXEN 1 + +#define ADC_CTRL_ON 0x0F +#define ADC_CTRL_OFF 0x00 + +// crazy order that matches the labels on the case + +#define LED_A (1 << 4) +#define LED_B (1 << 1) +#define LED_C (1 << 3) +#define LED_D (1 << 0) +#define LED_E (1 << 2) +// LED_F // controlled by CPLD +#define LED_RJ45 (1 << 5) + +#define output_regs ((output_regs_t *) MISC_OUTPUT_BASE) + +// --- udp tx regs --- + +typedef struct { + // Bits 19:16 are control info; bits 15:0 are data (see below) + // First two words are unused. + volatile uint32_t _nope[2]; + //--- ethernet header - 14 bytes--- + volatile struct{ + uint32_t mac_dst_0_1; //word 2 + uint32_t mac_dst_2_3; + uint32_t mac_dst_4_5; + uint32_t mac_src_0_1; + uint32_t mac_src_2_3; + uint32_t mac_src_4_5; + uint32_t ether_type; //word 8 + } eth_hdr; + //--- ip header - 20 bytes --- + volatile struct{ + uint32_t ver_ihl_tos; //word 9 + uint32_t total_length; + uint32_t identification; + uint32_t flags_frag_off; + uint32_t ttl_proto; + uint32_t checksum; + uint32_t src_addr_high; + uint32_t src_addr_low; + uint32_t dst_addr_high; + uint32_t dst_addr_low; //word 18 + } ip_hdr; + //--- udp header - 8 bytes --- + volatile struct{ + uint32_t src_port; //word 19 + uint32_t dst_port; + uint32_t length; + uint32_t checksum; //word 22 + } udp_hdr; + volatile uint32_t _pad[32-23]; +} sr_udp_sm_t; + +// control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) + +// This is the last word of the header +#define UDP_SM_LAST_WORD (1 << 19) + +// Insert IP header checksum here. Data is the xor of 16'hFFFF and +// the values written into regs 9-13 and 15-18. +#define UDP_SM_INS_IP_HDR_CHKSUM (1 << 18) + +// Insert IP Length here (data ignored) +#define UDP_SM_INS_IP_LEN (1 << 17) + +// Insert UDP Length here (data ignore) +#define UDP_SM_INS_UDP_LEN (1 << 16) + +#define sr_udp_sm ((sr_udp_sm_t *) _SR_ADDR(SR_UDP_SM)) + +// --- dsp tx regs --- + +#define MIN_CIC_INTERP 1 +#define MAX_CIC_INTERP 128 + +typedef struct { + volatile uint32_t num_chan; + volatile uint32_t clear_state; // clears out state machine, fifos, +} sr_tx_ctrl_t; + +#define sr_tx_ctrl ((sr_tx_ctrl_t *) _SR_ADDR(SR_TX_CTRL)) + +typedef struct { + volatile int32_t freq; + volatile uint32_t scale_iq; // {scale_i,scale_q} + volatile uint32_t interp_rate; + volatile uint32_t _padding0; // padding for the tx_mux + // NOT freq, scale, interp + /*! + * \brief output mux configuration. + * + *
+   *     3                   2                   1                       
+   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   *  +-------------------------------+-------+-------+-------+-------+
+   *  |                                               | DAC1  |  DAC0 |
+   *  +-------------------------------+-------+-------+-------+-------+
+   * 
+   *  There are N DUCs (1 now) with complex inputs and outputs.
+   *  There are two DACs.
+   * 
+   *  Each 4-bit DACx field specifies the source for the DAC
+   *  Each subfield is coded like this: 
+   * 
+   *     3 2 1 0
+   *    +-------+
+   *    |   N   |
+   *    +-------+
+   * 
+   *  N specifies which DUC output is connected to this DAC.
+   * 
+   *   N   which interp output
+   *  ---  -------------------
+   *   0   DUC 0 I
+   *   1   DUC 0 Q
+   *   2   DUC 1 I
+   *   3   DUC 1 Q
+   *   F   All Zeros
+   *   
+   * The default value is 0x10
+   * 
+ */ + volatile uint32_t tx_mux; + +} dsp_tx_regs_t; + +#define dsp_tx_regs ((dsp_tx_regs_t *) _SR_ADDR(SR_TX_DSP)) + +// --- VITA RX CTRL regs --- +typedef struct { + // The following 3 are logically a single command register. + // They are clocked into the underlying fifo when time_ticks is written. + volatile uint32_t cmd; // {now, chain, num_samples(30) + volatile uint32_t time_secs; + volatile uint32_t time_ticks; + + volatile uint32_t clear_overrun; // write anything to clear overrun + volatile uint32_t vrt_header; // word 0 of packet. FPGA fills in packet counter + volatile uint32_t vrt_stream_id; // word 1 of packet. + volatile uint32_t vrt_trailer; + volatile uint32_t nsamples_per_pkt; + volatile uint32_t nchannels; // 1 in basic case, up to 4 for vector sources + volatile uint32_t pad[7]; // Make each structure 16 elements long +} sr_rx_ctrl_t; + +#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL)) + +// --- dsp rx regs --- +#define MIN_CIC_DECIM 1 +#define MAX_CIC_DECIM 128 + +typedef struct { + volatile int32_t freq; + volatile uint32_t scale_iq; // {scale_i,scale_q} + volatile uint32_t decim_rate; + volatile uint32_t dcoffset_i; // Bit 31 high sets fixed offset mode, using lower 14 bits, + // otherwise it is automatic + volatile uint32_t dcoffset_q; // Bit 31 high sets fixed offset mode, using lower 14 bits + + /*! + * \brief input mux configuration. + * + * This determines which ADC (or constant zero) is connected to + * each DDC input. There are N DDCs (1 now). Each has two inputs. + * + *
+   * Mux value:
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   * |                                                       |Q0 |I0 |
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   *
+   * Each 2-bit I field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
+   * Each 2-bit Q field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
+   *
+   * The default value is 0x4
+   * 
+ */ + volatile uint32_t rx_mux; // called adc_mux in dsp_core_rx.v + + /*! + * \brief Streaming GPIO configuration + * + * This determines whether the LSBs of I and Q samples come from the DSP + * pipeline or from the io_rx GPIO pins. To stream GPIO, one must first + * set the GPIO data direction register to have io_rx[15] and/or io_rx[14] + * configured as inputs. The GPIO pins will be sampled at the time the + * remainder of the DSP sample is strobed into the RX sample FIFO. There + * will be a decimation-dependent fixed time offset between the GPIO + * sample stream and the associated RF samples. + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | MBZ |Q|I| + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * I 0=LSB comes from DSP pipeline (default) + * 1=LSB comes from io_rx[15] + * + * Q 0=LSB comes from DSP pipeline (default) + * 1=LSB comes from io_rx[14] + */ + volatile uint32_t gpio_stream_enable; + +} dsp_rx_regs_t; + +#define dsp_rx_regs ((dsp_rx_regs_t *) _SR_ADDR(SR_RX_DSP)) + +// ---------------------------------------------------------------- +// VITA49 64 bit time (write only) + /*! + * \brief Time 64 flags + * + *
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-----------------------------------------------------------+-+-+
+   * |                                                           |S|P|
+   * +-----------------------------------------------------------+-+-+
+   *
+   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
+   * S - Source (0=sma, 1=mimo, 0=default)
+   *
+   * 
+ */ +typedef struct { + volatile uint32_t secs; // value to set absolute secs to on next PPS + volatile uint32_t ticks; // value to set absolute ticks to on next PPS + volatile uint32_t flags; // flags - see chart above + volatile uint32_t imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0) +} sr_time64_t; + +#define sr_time64 ((sr_time64_t *) _SR_ADDR(SR_TIME64)) + + +/* + * --- ethernet tx protocol engine regs (write only) --- + * + * These registers control the transmit portion of the ethernet + * protocol engine (out of USRP2). The protocol engine handles fifo + * status and sequence number insertion in outgoing packets, and + * automagically generates status packets when required to inform the + * host of changes in fifo availability. + * + * All outgoing packets have their fifo_status field set to the number + * of 32-bit lines of fifo available in the ethernet Rx fifo (see + * usrp2_eth_packet.h). Seqno's are set if FIXME, else 0. + * + * FIXME clean this up once we know how it's supposed to behave. + */ + +typedef struct { + volatile uint32_t flags; // not yet fully defined (channel?) + volatile uint32_t mac_dst0123; // 4 bytes of destination mac addr + volatile uint32_t mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr + volatile uint32_t mac_src2345; // 4 bytes of destination mac addr + volatile uint32_t seqno; // Write to init seqno. It autoincs on match +} tx_proto_engine_regs_t; + +#define tx_proto_engine ((tx_proto_engine_regs_t *) TX_PROTOCOL_ENGINE_BASE) + +/* + * --- ethernet rx protocol engine regs (write only) --- + * + * These registers control the receive portion of the ethernet + * protocol engine (into USRP2). The protocol engine offloads common + * packet inspection operations so that firmware has less to do on + * "fast path" packets. + * + * The registers define conditions which must be matched for a packet + * to be considered a "fast path" packet. If a received packet + * matches the src and dst mac address, ethertype, flags field, and + * expected seqno number it is considered a "fast path" packet, and + * the expected seqno is updated. If the packet fails to satisfy any + * of the above conditions it's a "slow path" packet, and the + * corresponding SLOWPATH flag will be set buffer_status register. + */ + +typedef struct { + volatile uint32_t flags; // not yet fully defined (channel?) + volatile uint32_t mac_dst0123; // 4 bytes of destination mac addr + volatile uint32_t mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr + volatile uint32_t mac_src2345; // 4 bytes of destination mac addr + volatile uint32_t ethertype_pad; // ethertype in high 16-bits +} rx_proto_engine_regs_t; + +#define rx_proto_engine ((rx_proto_engine_regs_t *) RX_PROTOCOL_ENGINE_BASE) + + + +/////////////////////////////////////////////////// +// Simple Programmable Interrupt Controller, Slave 8 + +#define PIC_BASE 0x3500 + +// Interrupt request lines +// Bit numbers (LSB == 0) that correpond to interrupts into PIC + +#define IRQ_BUFFER 0 // buffer manager +#define IRQ_ONETIME 1 +#define IRQ_SPI 2 +#define IRQ_I2C 3 +#define IRQ_PHY 4 // ethernet PHY +#define IRQ_UNDERRUN 5 +#define IRQ_OVERRUN 6 +#define IRQ_PPS 7 // pulse per second +#define IRQ_UART_RX 8 +#define IRQ_UART_TX 9 +#define IRQ_SERDES 10 +#define IRQ_CLKSTATUS 11 +#define IRQ_PERIODIC 12 +#define IRQ_BUTTON 13 + +#define IRQ_TO_MASK(x) (1 << (x)) + +#define PIC_BUFFER_INT IRQ_TO_MASK(IRQ_BUFFER) +#define PIC_ONETIME_INT IRQ_TO_MASK(IRQ_ONETIME) +#define PIC_SPI_INT IRQ_TO_MASK(IRQ_SPI) +#define PIC_I2C_INT IRQ_TO_MASK(IRQ_I2C) +#define PIC_PHY_INT IRQ_TO_MASK(IRQ_PHY) +#define PIC_UNDERRUN_INT IRQ_TO_MASK(IRQ_UNDERRUN) +#define PIC_OVERRUN_INT IRQ_TO_MASK(IRQ_OVERRUN) +#define PIC_PPS_INT IRQ_TO_MASK(IRQ_PPS) +#define PIC_UART_RX_INT IRQ_TO_MASK(IRQ_UART_RX) +#define PIC_UART_TX_INT IRQ_TO_MASK(IRQ_UART_TX) +#define PIC_SERDES IRQ_TO_MASK(IRQ_SERDES) +#define PIC_CLKSTATUS IRQ_TO_MASK(IRQ_CLKSTATUS) +#define PIC_BUTTON IRQ_TO_MASK(IRQ_BUTTON) + +typedef struct { + volatile uint32_t edge_enable; // mask: 1 -> edge triggered, 0 -> level + volatile uint32_t polarity; // mask: 1 -> rising edge + volatile uint32_t mask; // mask: 1 -> disabled + volatile uint32_t pending; // mask: 1 -> pending; write 1's to clear pending ints +} pic_regs_t; + +#define pic_regs ((pic_regs_t *) PIC_BASE) + +// ---------------------------------------------------------------- +// WB_CLK_RATE is the time base for this +typedef struct { + volatile uint32_t onetime; // Number of wb clk cycles till the onetime interrupt + volatile uint32_t periodic; // Repeat rate of periodic interrupt +} sr_simple_timer_t; + +#define sr_simple_timer ((sr_simple_timer_t *) _SR_ADDR(SR_SIMTIMER)) + +/////////////////////////////////////////////////// +// UNUSED, Slave 9 + +/////////////////////////////////////////////////// +// UART, Slave 10 + +#define UART_BASE 0x3700 + +typedef struct { + // All elements are 8 bits except for clkdiv (16), but we use uint32 to make + // the hardware for decoding easier + volatile uint32_t clkdiv; // Set to 50e6 divided by baud rate (no x16 factor) + volatile uint32_t txlevel; // Number of spaces in the FIFO for writes + volatile uint32_t rxlevel; // Number of available elements in the FIFO for reads + volatile uint32_t txchar; // Write characters to be sent here + volatile uint32_t rxchar; // Read received characters here +} uart_regs_t; + +#define uart_regs ((uart_regs_t *) UART_BASE) + +/////////////////////////////////////////////////// +// ATR Controller, Slave 11 + +#define ATR_BASE 0x3800 + +typedef struct { + volatile uint32_t v[16]; +} atr_regs_t; + +#define ATR_IDLE 0x0 // indicies into v +#define ATR_TX 0x1 +#define ATR_RX 0x2 +#define ATR_FULL 0x3 + +#define atr_regs ((atr_regs_t *) ATR_BASE) + +/////////////////////////////////////////////////// +// UNUSED, Slave 12 + +/////////////////////////////////////////////////// +// ICAP, Slave 13 + +#define ICAP_BASE 0x3A00 +typedef struct { + uint32_t icap; //only the lower 8 bits matter +} icap_regs_t; + +#define icap_regs ((icap_regs_t *) ICAP_BASE) + +/////////////////////////////////////////////////// +// SPI Flash interface, Slave 14 +// Control register definitions are the same as SPI, so use SPI_CTRL_ASS, etc. +// Peripheral mask not needed since bus is dedicated (CE held low) + +#define SPIF_BASE 0x3B00 +typedef struct { + volatile uint32_t txrx0; + volatile uint32_t txrx1; + volatile uint32_t txrx2; + volatile uint32_t txrx3; + volatile uint32_t ctrl; + volatile uint32_t div; + volatile uint32_t ss; +} spif_regs_t; + +#define spif_regs ((spif_regs_t *) SPIF_BASE) + +//////////////////////////////////////////////////////////////// +// Main RAM, Slave 15 + +#define RAM_BASE 0x8000 + + + +/////////////////////////////////////////////////// +#endif + diff --git a/firmware/microblaze/usrp2p/spi_flash.c b/firmware/microblaze/usrp2p/spi_flash.c new file mode 100644 index 000000000..09b74a513 --- /dev/null +++ b/firmware/microblaze/usrp2p/spi_flash.c @@ -0,0 +1,194 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + * Copyright 2009 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 "spi_flash_private.h" +//#include +#include + +uint32_t +spi_flash_rdsr(void) +{ + return spif_transact(SPI_TXRX, SPI_SS_FLASH, RDSR_CMD << 8, 16, FLAGS) & 0xff; +} + +static void +spi_flash_write_enable(void) +{ +// spif_transact(SPI_TXONLY, SPI_SS_FLASH, (WRSR_CMD << 8) | 0x00, 16, FLAGS); //disable write protection bits + spif_transact(SPI_TXONLY, SPI_SS_FLASH, WREN_CMD, 8, FLAGS); +} + +bool +spi_flash_done_p(void) +{ + return (spi_flash_rdsr() & SR_WIP) == 0; +} + +void +spi_flash_wait(void) +{ + while (!spi_flash_done_p()) + ; +} + +void +spi_flash_erase_sector_start(uint32_t flash_addr) +{ + //uprintf(UART_DEBUG, "spi_flash_erase_sector_start: addr = 0x%x\n", flash_addr); + + spi_flash_wait(); + spi_flash_write_enable(); + spif_transact(SPI_TXONLY, SPI_SS_FLASH, + (SE_CMD << 24) | (flash_addr & 0x00ffffff), + 32, FLAGS); +} + +bool +spi_flash_page_program_start(uint32_t flash_addr, size_t nbytes, const void *buf) +{ + if (nbytes == 0 || nbytes > SPI_FLASH_PAGE_SIZE) + return false; + + uint32_t local_buf[SPI_FLASH_PAGE_SIZE / sizeof(uint32_t)]; + memset(local_buf, 0xff, sizeof(local_buf)); // init to 0xff (nops when programming) + memcpy(local_buf, buf, nbytes); + + spi_flash_wait(); + spi_flash_write_enable(); + + /* + * We explicitly control the slave select here (/S), so that we can + * do the entire write operation as a single transaction from + * device's point of view. (The most our SPI peripheral can transfer + * in a single shot is 16 bytes.) + */ + spif_wait(); + + spif_regs->ss = 0; + spif_regs->ctrl = FLAGS; // ASS is now clear and no chip select is enabled. + + /* write PP_CMD, ADDR2, ADDR1, ADDR0 */ + + spif_regs->txrx0 = (PP_CMD << 24) | (flash_addr & 0x00ffffff); + spif_regs->ss = SPI_SS_FLASH; // assert chip select + spif_regs->ctrl = FLAGS | LEN(4 * 8); + spif_regs->ctrl = FLAGS | LEN(4 * 8) | SPI_CTRL_GO_BSY; + spif_wait(); + + /* send 256 bytes total, 16 at a time */ + for (size_t i = 0; i < 16; i++){ + spif_regs->txrx3 = local_buf[i * 4 + 0]; + spif_regs->txrx2 = local_buf[i * 4 + 1]; + spif_regs->txrx1 = local_buf[i * 4 + 2]; + spif_regs->txrx0 = local_buf[i * 4 + 3]; + + spif_regs->ctrl = FLAGS | LEN(16 * 8); // xfer 16 bytes + spif_regs->ctrl = FLAGS | LEN(16 * 8) | SPI_CTRL_GO_BSY; + spif_wait(); + } + spif_regs->ss = 0; // desassert chip select + + return true; +} + +void +spi_flash_erase(uint32_t flash_addr, size_t nbytes) +{ + if (nbytes == 0) + return; + + uint32_t first = round_down(flash_addr, spi_flash_sector_size()); + uint32_t last = round_down(flash_addr + nbytes - 1, spi_flash_sector_size()); + + for (uint32_t s = first; s <= last; s += spi_flash_sector_size()){ + spi_flash_erase_sector_start(s); + } + spi_flash_wait(); +} + +bool +spi_flash_program(uint32_t flash_addr, size_t nbytes, const void *buf) +{ + //uprintf(UART_DEBUG, "\nspi_flash_program: addr = 0x%x, nbytes = %d\n", flash_addr, nbytes); + + const unsigned char *p = (const unsigned char *) buf; + size_t n; + + if (nbytes == 0) + return true; + + uint32_t r = flash_addr % SPI_FLASH_PAGE_SIZE; + if (r){ /* do initial non-aligned page */ + n = min(SPI_FLASH_PAGE_SIZE - r, nbytes); + spi_flash_page_program_start(flash_addr, n, p); + flash_addr += n; + p += n; + nbytes -= n; + } + + while (nbytes > 0){ + n = min(SPI_FLASH_PAGE_SIZE, nbytes); + spi_flash_page_program_start(flash_addr, n, p); + flash_addr += n; + p += n; + nbytes -= n; + } + + spi_flash_wait(); + return true; +} + +void +spi_flash_async_erase_start(spi_flash_async_state_t *s, + uint32_t flash_addr, size_t nbytes) +{ + if (nbytes == 0){ + s->first = s->last = s->current = 0; + return; + } + + uint32_t first = round_down(flash_addr, spi_flash_sector_size()); + uint32_t last = round_down(flash_addr + nbytes - 1, spi_flash_sector_size()); + + s->first = first; + s->last = last; + s->current = first; + + spi_flash_erase_sector_start(s->current); +} + +bool +spi_flash_async_erase_poll(spi_flash_async_state_t *s) +{ + if (!spi_flash_done_p()) + return false; + + //printf("%d/%d\n", s->current, s->last); + + // The current sector erase has completed. See if we're finished or + // if there's more to do. + + if (s->current == s->last) // we're done! + return true; + + s->current += spi_flash_sector_size(); + spi_flash_erase_sector_start(s->current); + return false; +} + diff --git a/firmware/microblaze/usrp2p/spi_flash.h b/firmware/microblaze/usrp2p/spi_flash.h new file mode 100644 index 000000000..f65f28477 --- /dev/null +++ b/firmware/microblaze/usrp2p/spi_flash.h @@ -0,0 +1,112 @@ +/* -*- c -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + * Copyright 2009 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 . + */ +#ifndef INCLUDED_SPI_FLASH_H +#define INCLUDED_SPI_FLASH_H + +#include +#include +#include + + +#define SPI_FLASH_PAGE_SIZE 256 +#define SPI_SS_FLASH 1 + + +uint32_t spi_flash_rdid(void); /* Read ID */ +uint32_t spi_flash_rdsr(void); /* Read Status Register */ +size_t spi_flash_log2_sector_size(void) __attribute__((pure)); /* either 16 or 18 */ + +static inline size_t +spi_flash_sector_size(void) +{ + return ((size_t) 1) << spi_flash_log2_sector_size(); +} + +void spi_flash_read(uint32_t flash_addr, size_t nbytes, void *buf); + +/* + * Erase all sectors that fall within the interval [flash_addr, flash_addr + nbytes). + * Erasing sets the memory to ones. + */ +void spi_flash_erase(uint32_t flash_addr, size_t nbytes); + +/* + * Program the flash. + * The area must have been erased prior to programming. + */ +bool spi_flash_program(uint32_t flash_addr, size_t nbytes, const void *buf); + +/* + * --- asynchronous routines --- + */ + +/* + * Is the erasing or programming done? + */ +bool spi_flash_done_p(void); + +/* + * Wait for erasing or programming to complete + */ +void spi_flash_wait(void); + +/* + * Start the erase process on a single sector. + * (It takes between 1 and 3 seconds to erase a 64KB sector) + */ +void spi_flash_erase_sector_start(uint32_t flash_addr); + +/* + * Start the programming process within a single page. + * nbytes must be between 1 and 256. + * (It takes between 1.4 and 5 ms to program a page -> 640 ms for 64KB) + */ +bool spi_flash_page_program_start(uint32_t flash_addr, size_t nbytes, const void *buf); + + +/* + * --- high-level async erase --- + */ + +typedef struct { + uint32_t first; + uint32_t last; + uint32_t current; +} spi_flash_async_state_t; + +/* + * Start to erase all sectors that fall within the interval [flash_addr, flash_addr + nbytes). + * Erasing sets the memory to ones. + * + * Initializes s and begins the process. Call spi_flash_async_erase_poll + * to test for completion and advance state machine. + */ +void spi_flash_async_erase_start(spi_flash_async_state_t *s, + uint32_t flash_addr, size_t nbytes); + +/* + * Poll for aysnc flash erase completion. + * Returns true when the erase has completed. + * (This should be called at something >= 4 Hz. It takes 1 to 3 seconds to + * erase each 64KB sector). + */ +bool spi_flash_async_erase_poll(spi_flash_async_state_t *s); + + +#endif /* INCLUDED_SPI_FLASH_H */ diff --git a/firmware/microblaze/usrp2p/spi_flash_private.h b/firmware/microblaze/usrp2p/spi_flash_private.h new file mode 100644 index 000000000..9a1b8d3e3 --- /dev/null +++ b/firmware/microblaze/usrp2p/spi_flash_private.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + * Copyright 2009 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 . + */ + +#ifndef INCLUDED_SPI_FLASH_PRIVATE_H +#define INCLUDED_SPI_FLASH_PRIVATE_H + +#include "spi_flash.h" +#include "spi.h" +#include "memory_map.h" +#include + + +/* M25P64 et al. */ + +#define WREN_CMD 0x06 // write enable +#define WRDI_CMD 0x04 // write disable +#define RDID_CMD 0x9f // read identification +#define RDSR_CMD 0x05 // read status register +#define WRSR_CMD 0x01 // write status register +#define READ_CMD 0x03 +#define FAST_READ_CMD 0x0b +#define PP_CMD 0x02 // page program (256 bytes) +#define SE_CMD 0xd8 // sector erase (64KB) +#define BE_CMD 0xc7 // bulk erase (all) +#define RES_CMD 0xab // read electronic sig (deprecated) + +/* Status register bits */ + +#define SR_SRWD 0x80 +#define SR_BP2 0x10 // block protect bit 2 +#define SR_BP1 0x08 // block protect bit 1 +#define SR_BP0 0x04 // block protect bit 0 +#define SR_WEL 0x02 // Write Enable Latch +#define SR_WIP 0x01 // Write in Progress. Set if busy w/ program or erase cycle. + + +#define FLAGS (SPIF_PUSH_FALL | SPIF_LATCH_RISE) + +#define LEN(x) ((x) & SPI_CTRL_CHAR_LEN_MASK) + + +static inline uint32_t +min(uint32_t a, uint32_t b) +{ + return a < b ? a : b; +} + +static inline uint32_t +round_down(uint32_t x, uint32_t power_of_2) +{ + return x & -power_of_2; +} + +#endif /* INCLUDED_SPI_FLASH_PRIVATE_H */ diff --git a/firmware/microblaze/usrp2p/spi_flash_read.c b/firmware/microblaze/usrp2p/spi_flash_read.c new file mode 100644 index 000000000..1c65350f7 --- /dev/null +++ b/firmware/microblaze/usrp2p/spi_flash_read.c @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + * Copyright 2009 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 "spi_flash_private.h" +#include // abort + +uint32_t +spi_flash_rdid(void) +{ + return spif_transact(SPI_TXRX, SPI_SS_FLASH, RDID_CMD << 24, 32, FLAGS) & 0xffffff; +} + +size_t +spi_flash_log2_sector_size(void) +{ + static size_t _spi_flash_log2_sector_size; + + if (_spi_flash_log2_sector_size != 0) + return _spi_flash_log2_sector_size; + + + uint32_t id = spi_flash_rdid(); + int type = (id >> 8) & 0xff; + int size = id & 0xff; + if (type != 0x20 || size < 22 || size > 24) + abort(); + + static unsigned char log2_sector_size[3] = { + 16, /* M25P32 */ + 16, /* M25P64 */ + 18, /* M25P128 */ + }; + + _spi_flash_log2_sector_size = log2_sector_size[size - 22]; + return _spi_flash_log2_sector_size; +} + +void +spi_flash_read(uint32_t flash_addr, size_t nbytes, void *buf) +{ + /* + * We explicitly control the slave select here (/S), so that we can + * do the entire read operation as a single transaction from + * device's point of view. (The most our SPI peripheral can transfer + * in a single shot is 16 bytes.) + */ + spif_wait(); + + spif_regs->ss = 0; + spif_regs->ctrl = FLAGS; // ASS is now clear and no chip select is enabled. + + /* + * Do the 5 byte instruction tranfer: + * FAST_READ_CMD, ADDR2, ADDR1, ADDR0, DUMMY + */ + spif_regs->txrx1 = FAST_READ_CMD; + spif_regs->txrx0 = ((flash_addr & 0x00ffffff) << 8); + spif_regs->ss = SPI_SS_FLASH; // assert chip select + spif_regs->ctrl = FLAGS | LEN(5 * 8); + spif_regs->ctrl = FLAGS | LEN(5 * 8) | SPI_CTRL_GO_BSY; + spif_wait(); + + /* + * Read up to 16 bytes at a time until done + */ + unsigned char *dst = (unsigned char *) buf; + size_t m; + for (size_t n = 0; n < nbytes; n += m, dst += m){ + spif_regs->ctrl = FLAGS | LEN(16 * 8); // xfer 16 bytes + spif_regs->ctrl = FLAGS | LEN(16 * 8) | SPI_CTRL_GO_BSY; + spif_wait(); + + uint32_t w[4]; + w[0] = spif_regs->txrx3; // txrx3 has first bits in it + w[1] = spif_regs->txrx2; + w[2] = spif_regs->txrx1; + w[3] = spif_regs->txrx0; + unsigned char *src = (unsigned char *) &w[0]; + m = min(nbytes - n, 16); + for (size_t i = 0; i < m; i++) + dst[i] = src[i]; + } + spif_regs->ss = 0; // deassert chip select +} diff --git a/firmware/microblaze/usrp2p/spif.c b/firmware/microblaze/usrp2p/spif.c new file mode 100644 index 000000000..1c1a348f4 --- /dev/null +++ b/firmware/microblaze/usrp2p/spif.c @@ -0,0 +1,68 @@ +/* + * Copyright 2007,2008,2009 Free Software Foundation, Inc. + * Copyright 2009 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 . + */ + +/* + * Code for the Flash SPI bus + */ + +#include "spi.h" +#include "memory_map.h" + +void +spif_init(void) +{ + /* + * f_sclk = f_wb / ((div + 1) * 2) + */ + spif_regs->div = 1; // 0 = Div by 2 (31.25 MHz); 1 = Div-by-4 (15.625 MHz) + + // run dummy transaction to work around invalid initial clock state + spif_transact(SPI_TXONLY, 0, 0, 8, SPIF_PUSH_FALL | SPIF_LATCH_RISE); +} + +inline void +spif_wait(void) +{ + while (spif_regs->ctrl & SPI_CTRL_GO_BSY) + ; +} + +uint32_t +spif_transact(bool readback_, int slave, uint32_t data, int length, uint32_t flags) +{ + flags &= (SPI_CTRL_TXNEG | SPI_CTRL_RXNEG); + int ctrl = SPI_CTRL_ASS | (SPI_CTRL_CHAR_LEN_MASK & length) | flags; + + spif_wait(); + + // Data we will send + spif_regs->txrx0 = data; + + // Run it -- write once and rewrite with GO set + spif_regs->ctrl = ctrl; + // Tell it which SPI slave device to access + spif_regs->ss = slave & 0xff; + spif_regs->ctrl = ctrl | SPI_CTRL_GO_BSY; + + if(readback_) { + spif_wait(); + return spif_regs->txrx0; + } + else + return 0; +} diff --git a/firmware/microblaze/usrp2p/xilinx_s3_icap.h b/firmware/microblaze/usrp2p/xilinx_s3_icap.h new file mode 100644 index 000000000..7b7e9eccc --- /dev/null +++ b/firmware/microblaze/usrp2p/xilinx_s3_icap.h @@ -0,0 +1,37 @@ +/* -*- c -*- */ +/* + * Copyright 2009 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 . + */ + +#ifndef INCLUDED_XILINX_S3_ICAP_H +#define INCLUDED_XILINX_S3_ICAP_H + +#include + + +void wr_icap(uint8_t x); +uint8_t rd_icap(void); + +//int icap_read_config_reg(int regno); + +/* + * Attempt to reload the fpga from \p flash_address. + * Shouldn't return, but might. + */ +void icap_reload_fpga(uint32_t flash_address); + + +#endif /* INCLUDED_XILINX_S3_ICAP_H */ -- cgit v1.2.3 From 7aec87d83f9aea23e7e9c71cdfe26aab6105f43c Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 26 Jul 2010 15:47:01 -0700 Subject: Deleted manually those files to correspond with USRP2P branch. --- firmware/microblaze/apps/.gitignore | 8 - firmware/microblaze/apps/Makefile.am | 82 --- firmware/microblaze/apps/app_passthru_v2.c | 251 ------- firmware/microblaze/apps/app_passthru_v2.h | 54 -- firmware/microblaze/apps/blink_leds.c | 40 -- firmware/microblaze/apps/blink_leds2.c | 53 -- firmware/microblaze/apps/buf_ram_test.c | 89 --- firmware/microblaze/apps/burn_dbsrx_eeprom.c | 106 --- firmware/microblaze/apps/burnrev30.c | 162 ----- firmware/microblaze/apps/burnrev31.c | 162 ----- firmware/microblaze/apps/can_i_sub.c | 25 - firmware/microblaze/apps/double_buffer_fragment.c | 138 ---- firmware/microblaze/apps/echo.c | 34 - firmware/microblaze/apps/eth_serdes.c | 233 ------- firmware/microblaze/apps/factory_test.c | 438 ------------ firmware/microblaze/apps/gen_eth_packets.c | 187 ----- firmware/microblaze/apps/gen_pause_frames.c | 207 ------ firmware/microblaze/apps/hello.c | 30 - firmware/microblaze/apps/ibs_rx_test.c | 82 --- firmware/microblaze/apps/ibs_tx_test.c | 160 ----- firmware/microblaze/apps/mimo_app_common_v2.c | 582 ---------------- firmware/microblaze/apps/mimo_app_common_v2.h | 63 -- firmware/microblaze/apps/mimo_tx.c | 363 ---------- firmware/microblaze/apps/mimo_tx_slave.c | 376 ---------- firmware/microblaze/apps/rcv_eth_packets.c | 233 ------- firmware/microblaze/apps/read_dbids.c | 59 -- firmware/microblaze/apps/sd_bounce.c | 153 ----- firmware/microblaze/apps/sd_gentest.c | 269 -------- firmware/microblaze/apps/serdes_to_dsp.c | 179 ----- firmware/microblaze/apps/serdes_txrx.c | 368 ---------- firmware/microblaze/apps/set_hw_rev.c | 45 -- firmware/microblaze/apps/test1.c | 282 -------- firmware/microblaze/apps/test_db_spi.c | 35 - firmware/microblaze/apps/test_i2c.c | 108 --- firmware/microblaze/apps/test_lsadc.c | 57 -- firmware/microblaze/apps/test_lsdac.c | 51 -- firmware/microblaze/apps/test_phy_comm.c | 113 --- firmware/microblaze/apps/test_ram.c | 105 --- firmware/microblaze/apps/test_sd.c | 81 --- firmware/microblaze/apps/timer_test.c | 57 -- firmware/microblaze/apps/tx_standalone.c | 339 --------- firmware/microblaze/include/.gitignore | 2 - firmware/microblaze/include/Makefile.am | 30 - firmware/microblaze/include/compiler.h | 25 - firmware/microblaze/include/net/.gitignore | 2 - firmware/microblaze/include/net/Makefile.am | 23 - firmware/microblaze/include/net/eth_mac_addr.h | 29 - firmware/microblaze/include/net/padded_eth_hdr.h | 37 - firmware/microblaze/include/net/socket_address.h | 41 -- firmware/microblaze/include/usrp2_clock_bits.h | 55 -- firmware/microblaze/include/usrp2_fpga_regs.h | 80 --- firmware/microblaze/include/usrp2_i2c_addr.h | 78 --- firmware/microblaze/include/usrp2_types.h | 105 --- firmware/microblaze/include/vrt/bits.h | 92 --- firmware/microblaze/include/vrt/types.h | 138 ---- firmware/microblaze/lib/.gitignore | 40 -- firmware/microblaze/lib/Makefile.am | 87 --- firmware/microblaze/lib/clocks.c | 239 ------- firmware/microblaze/lib/memory_map.h | 792 ---------------------- firmware/microblaze/lib/sd.c | 197 ------ firmware/microblaze/lib/sd.h | 122 ---- host/lib/usrp/usrp2/usrp2_regs.cpp | 94 +++ host/lib/usrp/usrp2/usrp2_regs.hpp | 161 +++-- 63 files changed, 180 insertions(+), 8748 deletions(-) delete mode 100644 firmware/microblaze/apps/.gitignore delete mode 100644 firmware/microblaze/apps/Makefile.am delete mode 100644 firmware/microblaze/apps/app_passthru_v2.c delete mode 100644 firmware/microblaze/apps/app_passthru_v2.h delete mode 100644 firmware/microblaze/apps/blink_leds.c delete mode 100644 firmware/microblaze/apps/blink_leds2.c delete mode 100644 firmware/microblaze/apps/buf_ram_test.c delete mode 100644 firmware/microblaze/apps/burn_dbsrx_eeprom.c delete mode 100644 firmware/microblaze/apps/burnrev30.c delete mode 100644 firmware/microblaze/apps/burnrev31.c delete mode 100644 firmware/microblaze/apps/can_i_sub.c delete mode 100644 firmware/microblaze/apps/double_buffer_fragment.c delete mode 100644 firmware/microblaze/apps/echo.c delete mode 100644 firmware/microblaze/apps/eth_serdes.c delete mode 100644 firmware/microblaze/apps/factory_test.c delete mode 100644 firmware/microblaze/apps/gen_eth_packets.c delete mode 100644 firmware/microblaze/apps/gen_pause_frames.c delete mode 100644 firmware/microblaze/apps/hello.c delete mode 100644 firmware/microblaze/apps/ibs_rx_test.c delete mode 100644 firmware/microblaze/apps/ibs_tx_test.c delete mode 100644 firmware/microblaze/apps/mimo_app_common_v2.c delete mode 100644 firmware/microblaze/apps/mimo_app_common_v2.h delete mode 100644 firmware/microblaze/apps/mimo_tx.c delete mode 100644 firmware/microblaze/apps/mimo_tx_slave.c delete mode 100644 firmware/microblaze/apps/rcv_eth_packets.c delete mode 100644 firmware/microblaze/apps/read_dbids.c delete mode 100644 firmware/microblaze/apps/sd_bounce.c delete mode 100644 firmware/microblaze/apps/sd_gentest.c delete mode 100644 firmware/microblaze/apps/serdes_to_dsp.c delete mode 100644 firmware/microblaze/apps/serdes_txrx.c delete mode 100644 firmware/microblaze/apps/set_hw_rev.c delete mode 100644 firmware/microblaze/apps/test1.c delete mode 100644 firmware/microblaze/apps/test_db_spi.c delete mode 100644 firmware/microblaze/apps/test_i2c.c delete mode 100644 firmware/microblaze/apps/test_lsadc.c delete mode 100644 firmware/microblaze/apps/test_lsdac.c delete mode 100644 firmware/microblaze/apps/test_phy_comm.c delete mode 100644 firmware/microblaze/apps/test_ram.c delete mode 100644 firmware/microblaze/apps/test_sd.c delete mode 100644 firmware/microblaze/apps/timer_test.c delete mode 100644 firmware/microblaze/apps/tx_standalone.c delete mode 100644 firmware/microblaze/include/.gitignore delete mode 100644 firmware/microblaze/include/Makefile.am delete mode 100644 firmware/microblaze/include/compiler.h delete mode 100644 firmware/microblaze/include/net/.gitignore delete mode 100644 firmware/microblaze/include/net/Makefile.am delete mode 100644 firmware/microblaze/include/net/eth_mac_addr.h delete mode 100644 firmware/microblaze/include/net/padded_eth_hdr.h delete mode 100644 firmware/microblaze/include/net/socket_address.h delete mode 100644 firmware/microblaze/include/usrp2_clock_bits.h delete mode 100644 firmware/microblaze/include/usrp2_fpga_regs.h delete mode 100644 firmware/microblaze/include/usrp2_i2c_addr.h delete mode 100644 firmware/microblaze/include/usrp2_types.h delete mode 100644 firmware/microblaze/include/vrt/bits.h delete mode 100644 firmware/microblaze/include/vrt/types.h delete mode 100644 firmware/microblaze/lib/.gitignore delete mode 100644 firmware/microblaze/lib/Makefile.am delete mode 100644 firmware/microblaze/lib/clocks.c delete mode 100644 firmware/microblaze/lib/memory_map.h delete mode 100644 firmware/microblaze/lib/sd.c delete mode 100644 firmware/microblaze/lib/sd.h create mode 100644 host/lib/usrp/usrp2/usrp2_regs.cpp (limited to 'firmware') diff --git a/firmware/microblaze/apps/.gitignore b/firmware/microblaze/apps/.gitignore deleted file mode 100644 index 968b04cd7..000000000 --- a/firmware/microblaze/apps/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/*.elf -/*.bin -/*.dump -/*.log -/*.rom -/*.map -/Makefile -/Makefile.in diff --git a/firmware/microblaze/apps/Makefile.am b/firmware/microblaze/apps/Makefile.am deleted file mode 100644 index a4f79935b..000000000 --- a/firmware/microblaze/apps/Makefile.am +++ /dev/null @@ -1,82 +0,0 @@ -# -# Copyright 2010 Ettus Research LLC -# -# Copyright 2007,2008 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, see . -# - -include $(top_srcdir)/Makefile.common - -LDADD = $(top_srcdir)/lib/libu2fw.a - -AM_CFLAGS += -I$(top_srcdir)/../../host/lib/usrp - -noinst_PROGRAMS = txrx_uhd.elf - -# blink_leds \ -# blink_leds2 \ -# buf_ram_test \ -# burn_dbsrx_eeprom \ -# can_i_sub \ -# echo \ -# hello \ -# read_dbids \ -# set_hw_rev \ -# test1 \ -# test_db_spi \ -# test_i2c \ -# test_sd \ -# test_ram \ -# test_phy_comm \ -# test_lsadc \ -# test_lsdac \ -# timer_test \ -# txrx \ -# burnrev30 \ -# burnrev31 \ -# burnrev40 \ -# sd_gentest \ -# sd_bounce -# - -#nononono = \ -# eth_serdes \ -# gen_eth_packets \ -# rcv_eth_packets \ -# tx_standalone \ -# factory_test \ -# serdes_txrx \ -# mimo_tx \ -# mimo_tx_slave \ -# ibs_rx_test \ -# ibs_tx_test - -# tx_drop_SOURCES = tx_drop.c app_common.c -# tx_drop_rate_limited_SOURCES = tx_drop_rate_limited.c app_common.c -# tx_drop2_SOURCES = tx_drop2.c app_common.c -txrx_uhd_elf_SOURCES = txrx_uhd.c -# app_common_v2.c -#factory_test_SOURCES = factory_test.c app_common_v2.c -#eth_serdes_SOURCES = eth_serdes.c app_passthru_v2.c -#serdes_txrx_SOURCES = serdes_txrx.c app_common_v2.c -#mimo_tx_SOURCES = mimo_tx.c mimo_app_common_v2.c -#mimo_tx_slave_SOURCES = mimo_tx_slave.c app_common_v2.c - -#noinst_HEADERS = \ -# app_common_v2.h \ -# app_passthru_v2.h \ -# mimo_app_common_v2.h -# - diff --git a/firmware/microblaze/apps/app_passthru_v2.c b/firmware/microblaze/apps/app_passthru_v2.c deleted file mode 100644 index 406c56b3b..000000000 --- a/firmware/microblaze/apps/app_passthru_v2.c +++ /dev/null @@ -1,251 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "app_passthru_v2.h" -#include "buffer_pool.h" -#include "memcpy_wa.h" -#include "ethernet.h" -#include "nonstdio.h" -#include "print_rmon_regs.h" -#include "db.h" -#include "clocks.h" -#include - -volatile bool link_is_up = false; // eth handler sets this - - -// If this is non-zero, this dbsm could be writing to the ethernet -dbsm_t *ac_could_be_sending_to_eth; - -//static unsigned char exp_seqno = 0; - -void -set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt) -{ - reply_pkt->ehdr.dst = cmd_pkt->ehdr.src; - reply_pkt->ehdr.src = *ethernet_mac_addr(); - reply_pkt->ehdr.ethertype = U2_ETHERTYPE; - reply_pkt->thdr.flags = 0; - reply_pkt->thdr.fifo_status = 0; // written by protocol engine - reply_pkt->thdr.seqno = 0; // written by protocol engine - reply_pkt->thdr.ack = 0; // written by protocol engine - u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN); - reply_pkt->fixed.timestamp = timer_regs->time; -} - -static void -send_reply(unsigned char *reply, size_t reply_len) -{ - if (reply_len < 64) - reply_len = 64; - - // wait for buffer to become idle - hal_set_leds(0x4, 0x4); - while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0) - ; - hal_set_leds(0x0, 0x4); - - // copy reply into CPU_TX_BUF - memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len); - - // wait until nobody else is sending to the ethernet - if (ac_could_be_sending_to_eth){ - hal_set_leds(0x8, 0x8); - dbsm_wait_for_opening(ac_could_be_sending_to_eth); - hal_set_leds(0x0, 0x8); - } - - // fire it off - bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, reply_len/4); - - // wait for it to complete (not long, it's a small pkt) - while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0) - ; - - bp_clear_buf(CPU_TX_BUF); -} - - -static size_t -op_id_cmd(const op_generic_t *p, - void *reply_payload, size_t reply_payload_space) -{ - op_id_reply_t *r = (op_id_reply_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) // no room - return 0; - - // Build reply subpacket - - r->opcode = OP_ID_REPLY; - r->len = sizeof(op_id_reply_t); - r->rid = p->rid; - r->addr = *ethernet_mac_addr(); - r->hw_rev = 0x0000; // FIXME - // r->fpga_md5sum = ; // FIXME - // r->sw_md5sum = ; // FIXME - - // FIXME Add d'board info, including dbid, min/max gain, min/max freq - - return r->len; -} - -static size_t -add_eop(void *reply_payload, size_t reply_payload_space) -{ - op_generic_t *r = (op_generic_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) - return 0; // no room - - r->opcode = OP_EOP; - r->len = sizeof(*r); - r->rid = 0; - r->ok = 0; - - return r->len; -} - -bool -handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len) -{ - unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4; - unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)]; - int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t); - - bool handled_it = false; - - // initialize reply - memset(reply, 0, sizeof(reply)); - set_reply_hdr((u2_eth_packet_t *) reply, pkt); - - // point to beginning of payload (subpackets) - unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t); - int payload_len = len - sizeof(u2_eth_packet_t); - - size_t subpktlen = 0; - - while (payload_len >= sizeof(op_generic_t)){ - const op_generic_t *gp = (const op_generic_t *) payload; - subpktlen = 0; - - switch(gp->opcode){ - case OP_EOP: // end of subpackets - goto end_of_subpackets; - - case OP_ID: - subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space); - handled_it = true; - break; - - default: - if (0){ - printf("\npassing on %d\n", gp->opcode); - } - break; - } - - int t = (gp->len + 3) & ~3; // bump to a multiple of 4 - payload += t; - payload_len -= t; - - subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4 - reply_payload += subpktlen; - reply_payload_space -= subpktlen; - } - - end_of_subpackets: - - if (handled_it){ - // add the EOP marker - subpktlen = add_eop(reply_payload, reply_payload_space); - subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4 - reply_payload += subpktlen; - reply_payload_space -= subpktlen; - - send_reply(reply, reply_payload - reply); - } - - return handled_it; -} - - -/* - * Called when an ethernet packet is received. - * Return true if we handled it here, otherwise - * it'll be passed on to the DSP Tx pipe - */ -bool -eth_pkt_inspector(dbsm_t *sm, int bufno) -{ - u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno); - size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4; - - //static size_t last_len = 0; - - // hal_toggle_leds(0x1); - - // inspect rcvd frame and figure out what do do. - - if (pkt->ehdr.ethertype != U2_ETHERTYPE) - return true; // ignore, probably bogus PAUSE frame from MAC - - int chan = u2p_chan(&pkt->fixed); - - switch (chan){ - case CONTROL_CHAN: - return handle_control_chan_frame(pkt, byte_len); - break; - - case 0: - default: -#if 0 - if (last_len != 0){ - if (byte_len != last_len){ - printf("Len: %d last: %d\n", byte_len, last_len); - } - } - last_len = byte_len; - - if((pkt->thdr.seqno) == exp_seqno){ - exp_seqno++; - //putchar('.'); - } - else { - // putchar('S'); - //printf("S%d %d ",exp_seqno,pkt->thdr.seqno); - exp_seqno = pkt->thdr.seqno + 1; - } -#endif - return false; // pass it on to Tx DSP - break; - } -} - -/* - * Called when eth phy state changes (w/ interrupts disabled) - */ -void -link_changed_callback(int speed) -{ - link_is_up = speed != 0; - hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45); - printf("\neth link changed: speed = %d\n", speed); -} diff --git a/firmware/microblaze/apps/app_passthru_v2.h b/firmware/microblaze/apps/app_passthru_v2.h deleted file mode 100644 index 3904c670f..000000000 --- a/firmware/microblaze/apps/app_passthru_v2.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 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, see . - */ - -#ifndef INCLUDED_APP_COMMON_H -#define INCLUDED_APP_COMMON_H - -#include -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "memory_map.h" -#include "hal_io.h" -#include -#include - -#define CPU_TX_BUF 7 // cpu -> eth - -#define _AL4 __attribute__((aligned (4))) - -extern volatile bool link_is_up; // eth handler sets this - - -// If there's a dbsm that sends to the ethernet, put it's address here -extern dbsm_t *ac_could_be_sending_to_eth; - - -void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt); - -/* - * Called when an ethernet packet is received. - * Return true if we handled it here, otherwise - * it'll be passed on to the DSP Tx pipe - */ -bool eth_pkt_inspector(dbsm_t *sm, int bufno); - -void link_changed_callback(int speed); - -bool handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len); - -#endif /* INCLUDED_APP_COMMON_H */ diff --git a/firmware/microblaze/apps/blink_leds.c b/firmware/microblaze/apps/blink_leds.c deleted file mode 100644 index 682ca8db2..000000000 --- a/firmware/microblaze/apps/blink_leds.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "hal_io.h" -#include "nonstdio.h" - -int -main(void) -{ - int counter = 0; - - u2_init(); - - putstr("blink_leds\n"); - while(1){ - output_regs->leds = (counter++ & 0x3); - } - - return 0; -} diff --git a/firmware/microblaze/apps/blink_leds2.c b/firmware/microblaze/apps/blink_leds2.c deleted file mode 100644 index 13e78afb3..000000000 --- a/firmware/microblaze/apps/blink_leds2.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "hal_io.h" -#include "pic.h" -#include "nonstdio.h" - -//#define DELTA_T (MASTER_CLK_RATE/2) // 0.5s (10ns per tick) -#define DELTA_T 5000 // 5 us (10ns per tick) - - -void -timer_handler(unsigned irq) -{ - hal_set_timeout(DELTA_T); // schedule next timeout - hal_toggle_leds(0x2); -} - -int -main(void) -{ - u2_init(); - - putstr("blink_leds2\n"); - pic_register_handler(IRQ_ONETIME, timer_handler); - hal_set_timeout(DELTA_T); // schedule next timeout - - while(1){ - hal_toggle_leds(0x1); - } - - return 0; -} diff --git a/firmware/microblaze/apps/buf_ram_test.c b/firmware/microblaze/apps/buf_ram_test.c deleted file mode 100644 index 1aca2aec5..000000000 --- a/firmware/microblaze/apps/buf_ram_test.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#include "u2_init.h" -#include "memory_map.h" -#include -#include "nonstdio.h" -#include "hal_io.h" -#include "mdelay.h" - - -static void -write_bufs(void) -{ - int i, n; - int counter = 0; - - for (n = 0; n < NBUFFERS; n++){ - volatile int *p = buffer_ram(n); - for (i = 0; i < BP_NLINES; i++) - p[i] = counter++; - } -} - -// return number of errors detected -static int -check_bufs(void) -{ - int i, n; - int counter = 0; - int nerrors = 0; - - for (n = 0; n < NBUFFERS; n++){ - volatile int *p = buffer_ram(n); - for (i = 0; i < BP_NLINES; i++, counter++){ - int rd = p[i]; - if (rd != counter){ - putchar('b'); - putchar(n + '0'); - putchar('['); - puthex16(i); - putstr("] exp: "); - puthex32(counter); - putstr(" got: "); - puthex32_nl(rd); - nerrors++; - } - } - } - return nerrors; -} - - -int -main(void) -{ - u2_init(); - - output_regs->leds = 0; - - write_bufs(); - int nerrors = check_bufs(); - - if (nerrors == 0){ - output_regs->leds = 0x3; // leds on -> PASS - putstr("PASS\n"); - } - else { - output_regs->leds = 0x0; // leds off -> FAIL - putstr("FAIL\n"); - } - - hal_finish(); - return 0; -} diff --git a/firmware/microblaze/apps/burn_dbsrx_eeprom.c b/firmware/microblaze/apps/burn_dbsrx_eeprom.c deleted file mode 100644 index 116d4d8d0..000000000 --- a/firmware/microblaze/apps/burn_dbsrx_eeprom.c +++ /dev/null @@ -1,106 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "i2c.h" -#include "usrp2_i2c_addr.h" -#include "mdelay.h" -#include "hal_io.h" -#include "nonstdio.h" -#include - - - -int read_dboard_eeprom(int i2c_addr); - - -#define USRP_DBID_DBS_RX 0x0002 -#define USRP_DBID_DBS_RX_WITH_CLOCK_MOD 0x000d - -const char dbs_rx_rev2_eeprom[] = { - 0xdb, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18 -}; - -#define LED_VALS (LED_A | LED_B | LED_C | LED_D) -#define LED_MASK (LED_A | LED_B | LED_C | LED_D) - -int -main(void) -{ - u2_init(); - - puts("\nburn_dbsrx_eeprom\n"); - - hal_set_leds(0, ~0); // all off - - int i2c_addr = I2C_ADDR_RX_A; - int dbid = read_dboard_eeprom(i2c_addr); - bool ok; - const char *msg = 0; - - switch (dbid){ - case -1: - msg = "No RX daughterboard found"; - goto bad; - - case -2: - msg = "Invalid RX EEPROM contents"; - goto bad; - - case USRP_DBID_DBS_RX_WITH_CLOCK_MOD: - msg = "RX Daughterboard already reports being a DBS RX w/ CLOCK_MOD"; - goto good; - - case USRP_DBID_DBS_RX: - // Says it's a DBS_RX, attempt to burn the EEPROM - ok = eeprom_write(i2c_addr, 0, - dbs_rx_rev2_eeprom, sizeof(dbs_rx_rev2_eeprom)); - if (ok){ - msg = "Successfully programmed db as DBS RX Rev 2.1"; - goto good; - } - else { - msg = "Failed to write daugherboard eeprom"; - goto bad; - } - - default: - msg = "Daughterboard is not a DBS RX; ignored"; - goto bad; - } - - good: - puts(msg); - hal_set_leds(LED_VALS, LED_MASK); - while (1) - ; - - bad: - puts(msg); - while(1){ - hal_toggle_leds(LED_VALS); - mdelay(50); - } -} diff --git a/firmware/microblaze/apps/burnrev30.c b/firmware/microblaze/apps/burnrev30.c deleted file mode 100644 index 40fa53e34..000000000 --- a/firmware/microblaze/apps/burnrev30.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2007,2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "app_common_v2.h" -#include "memcpy_wa.h" -#include -#include -#include -#include -#include -#include -#include "sd.h" -#include "mdelay.h" - -#define HW_REV_MAJOR 3 -#define HW_REV_MINOR 0 - -int test_ram() -{ - int i,j,k; - output_regs->ram_page = 1<<10; - - extram[0] = 0xDEADBEEF; - extram[1] = 0xF00D1234; - extram[7] = 0x76543210; - - output_regs->ram_page = 2<<10; - extram[7] = 0x55555555; - extram[1] = 0xaaaaaaaa; - extram[0] = 0xeeeeeeee; - - output_regs->ram_page = 1<<10; - - i = extram[0]; - k = extram[1]; - j = extram[7]; - - if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { - puts("RAM FAIL1!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - - output_regs->ram_page = 2<<10; - - j = extram[7]; - k = extram[1]; - i = extram[0]; - - if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { - puts("RAM FAIL2!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - return 1; -} - -int test_sd() -{ - int i = sd_init(); - if(i==0) { - puts("FAILED INIT of Card\n"); - return 0; - } - - unsigned char buf[512]; - i = sd_read_block(2048,buf); - if(i == 0) { - puts("READ Command Rejected\n"); - return 0; - } - if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50)) - ; - else { - puts("Read bad data from SD Card\n"); - return 0; - } - return 1; -} - -int -main(void) -{ - u2_init(); - - putstr("\nFactory Test, Board Rev 3.0\n"); - - bool ok = true; - unsigned char maj = HW_REV_MAJOR; - unsigned char min = HW_REV_MINOR; - ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1); - ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1); - - putstr("\nset_hw_rev\n"); - if (ok) - printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); - else { - printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); - hal_finish(); - return 0; - } - - if(test_sd()) - puts("SD OK\n"); - else { - puts("SD FAIL\n"); - //hal_finish(); - //return 0; - } - if(test_ram()) - puts("RAM OK\n"); - else { - puts("RAM FAIL\n"); - hal_finish(); - return 0; - } - - print_mac_addr(ethernet_mac_addr()->addr); - newline(); - - clocks_mimo_config(MC_WE_LOCK_TO_SMA); - - while (!clocks_lock_detect()) { - puts("No Lock"); - mdelay(1000); - } - puts("Clock Locked\n"); - -} diff --git a/firmware/microblaze/apps/burnrev31.c b/firmware/microblaze/apps/burnrev31.c deleted file mode 100644 index f6b08d187..000000000 --- a/firmware/microblaze/apps/burnrev31.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2007,2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "app_common_v2.h" -#include "memcpy_wa.h" -#include -#include -#include -#include -#include -#include -#include "sd.h" -#include "mdelay.h" - -#define HW_REV_MAJOR 3 -#define HW_REV_MINOR 1 - -int test_ram() -{ - int i,j,k; - output_regs->ram_page = 1<<10; - - extram[0] = 0xDEADBEEF; - extram[1] = 0xF00D1234; - extram[7] = 0x76543210; - - output_regs->ram_page = 2<<10; - extram[7] = 0x55555555; - extram[1] = 0xaaaaaaaa; - extram[0] = 0xeeeeeeee; - - output_regs->ram_page = 1<<10; - - i = extram[0]; - k = extram[1]; - j = extram[7]; - - if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { - puts("RAM FAIL1!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - - output_regs->ram_page = 2<<10; - - j = extram[7]; - k = extram[1]; - i = extram[0]; - - if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { - puts("RAM FAIL2!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - return 1; -} - -int test_sd() -{ - int i = sd_init(); - if(i==0) { - puts("FAILED INIT of Card\n"); - return 0; - } - - unsigned char buf[512]; - i = sd_read_block(2048,buf); - if(i == 0) { - puts("READ Command Rejected\n"); - return 0; - } - if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50)) - ; - else { - puts("Read bad data from SD Card\n"); - return 0; - } - return 1; -} - -int -main(void) -{ - u2_init(); - - putstr("\nFactory Test, Board Rev 3.1\n"); - - bool ok = true; - unsigned char maj = HW_REV_MAJOR; - unsigned char min = HW_REV_MINOR; - ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1); - ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1); - - putstr("\nset_hw_rev\n"); - if (ok) - printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); - else { - printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); - hal_finish(); - return 0; - } - - if(test_sd()) - puts("SD OK\n"); - else { - puts("SD FAIL\n"); - //hal_finish(); - //return 0; - } - if(test_ram()) - puts("RAM OK\n"); - else { - puts("RAM FAIL\n"); - hal_finish(); - return 0; - } - - print_mac_addr(ethernet_mac_addr()->addr); - newline(); - - clocks_mimo_config(MC_WE_LOCK_TO_SMA); - - while (!clocks_lock_detect()) { - puts("No Lock"); - mdelay(1000); - } - puts("Clock Locked\n"); - -} diff --git a/firmware/microblaze/apps/can_i_sub.c b/firmware/microblaze/apps/can_i_sub.c deleted file mode 100644 index ed49791f0..000000000 --- a/firmware/microblaze/apps/can_i_sub.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -//typedef long long int64_t; - - -int64_t sub(int64_t a, int64_t b); -void print(int64_t d); - -int main(void) -{ - u2_init(); - - int64_t d = sub(462550990848000LL, 462028800000000LL); - print_uint64(d); - newline(); - return 0; -} - -int64_t sub(int64_t a, int64_t b) -{ - return a - b; -} - - diff --git a/firmware/microblaze/apps/double_buffer_fragment.c b/firmware/microblaze/apps/double_buffer_fragment.c deleted file mode 100644 index cfc061247..000000000 --- a/firmware/microblaze/apps/double_buffer_fragment.c +++ /dev/null @@ -1,138 +0,0 @@ -#if 0 -void -double_buffering(int port) { - unsigned int localstatus = buffer_pool_status->status; - - if(localstatus & BPS_DONE_0) { - bp_clear_buf(0); - if(buffer_state[0] == FILLING) { - buffer_state[0] = FULL; - if(buffer_state[1] == EMPTY) { - bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines - buffer_state[1] = FILLING; - } - else - dsp_rx_idle = 1; - if(serdes_tx_idle) { - serdes_tx_idle = 0; - bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0 - buffer_state[0] = EMPTYING; - } - } - else { // buffer was emptying - buffer_state[0] = EMPTY; - if(dsp_rx_idle) { - dsp_rx_idle = 0; - bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines - buffer_state[0] = FILLING; - } - if(buffer_state[1] == FULL) { - bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1 - buffer_state[1] = EMPTYING; - } - else - serdes_tx_idle = 1; - } - putstr("Int Proc'ed 0\n"); - } - - if(localstatus & BPS_DONE_1) { - bp_clear_buf(1); - if(buffer_state[1] == FILLING) { - buffer_state[1] = FULL; - if(buffer_state[0] == EMPTY) { - bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines - buffer_state[0] = FILLING; - } - else - dsp_rx_idle = 1; - if(serdes_tx_idle) { - serdes_tx_idle = 0; - bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1 - buffer_state[1] = EMPTYING; - } - } - else { // buffer was emptying - buffer_state[1] = EMPTY; - if(dsp_rx_idle) { - dsp_rx_idle = 0; - bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines - buffer_state[1] = FILLING; - } - if(buffer_state[0] == FULL) { - bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0 - buffer_state[0] = EMPTYING; - } - else - serdes_tx_idle = 1; - } - putstr("Int Proc'ed 1\n"); - } - - if(localstatus & BPS_DONE_2) { - bp_clear_buf(2); - if(buffer_state[2] == FILLING) { - buffer_state[2] = FULL; - if(buffer_state[3] == EMPTY) { - bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3, use 500 lines - buffer_state[3] = FILLING; - } - else - serdes_rx_idle = 1; - if(dsp_tx_idle) { - dsp_tx_idle = 0; - bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2 - buffer_state[2] = EMPTYING; - } - } - else { // buffer was emptying - buffer_state[2] = EMPTY; - if(serdes_rx_idle) { - serdes_rx_idle = 0; - bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2 - buffer_state[2] = FILLING; - } - if(buffer_state[3] == FULL) { - bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3 - buffer_state[3] = EMPTYING; - } - else - dsp_tx_idle = 1; - } - putstr("Int Proc'ed 2\n"); - } - - if(localstatus & BPS_DONE_3) { - bp_clear_buf(3); - if(buffer_state[3] == FILLING) { - buffer_state[3] = FULL; - if(buffer_state[2] == EMPTY) { - bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2, use 500 lines - buffer_state[2] = FILLING; - } - else - serdes_rx_idle = 1; - if(dsp_tx_idle) { - dsp_tx_idle = 0; - bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3 - buffer_state[3] = EMPTYING; - } - } - else { // buffer was emptying - buffer_state[3] = EMPTY; - if(serdes_rx_idle) { - serdes_rx_idle = 0; - bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3 - buffer_state[3] = FILLING; - } - if(buffer_state[2] == FULL) { - bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2 - buffer_state[2] = EMPTYING; - } - else - dsp_tx_idle = 1; - } - putstr("Int Proc'ed 3\n"); - } -} -#endif diff --git a/firmware/microblaze/apps/echo.c b/firmware/microblaze/apps/echo.c deleted file mode 100644 index 89108ee80..000000000 --- a/firmware/microblaze/apps/echo.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2008 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, see . - */ - -#include "u2_init.h" -#include "stdio.h" - -int -main(void) -{ - u2_init(); - - puts("\n>>> echo <<<"); - - while (1){ - int ch = getchar(); - putchar(ch); - } - - return 0; -} diff --git a/firmware/microblaze/apps/eth_serdes.c b/firmware/microblaze/apps/eth_serdes.c deleted file mode 100644 index 2d2ddc1ca..000000000 --- a/firmware/microblaze/apps/eth_serdes.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2007,2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "app_passthru_v2.h" -#include "memcpy_wa.h" -#include "clocks.h" -#include -#include -#include - - -#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) - -#if (FW_SETS_SEQNO) -static int fw_seqno __attribute__((unused)); // used when f/w is filling in sequence numbers -#endif - - -/* - * Full duplex Tx and Rx between ethernet and serdes - * - * Buffer 1 is used by the cpu to send frames to the host. - * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow - * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow - */ -//#define CPU_RX_BUF 0 // eth -> cpu - -#define DSP_RX_BUF_0 2 // serdes -> eth (double buffer) -#define DSP_RX_BUF_1 3 // serdes -> eth -#define DSP_TX_BUF_0 4 // eth -> serdes (double buffer) -#define DSP_TX_BUF_1 5 // eth -> serdes - -/* - * ================================================================ - * configure serdes double buffering state machine (eth -> serdes) - * ================================================================ - */ - - -// Receive from ethernet -buf_cmd_args_t dsp_tx_recv_args = { - PORT_ETH, - 0, - BP_LAST_LINE -}; - -// send to serdes -buf_cmd_args_t dsp_tx_send_args = { - PORT_SERDES, - 0, - 0 // filled in from last_line register -}; - -dbsm_t dsp_tx_sm; // the state machine - -/* - * ==================================================================== - * configure serdes RX double buffering state machine (serdes -> eth) - * ==================================================================== - */ - -// receive from serdes -buf_cmd_args_t dsp_rx_recv_args = { - PORT_SERDES, - 0, - BP_LAST_LINE -}; - -// send to ETH -buf_cmd_args_t dsp_rx_send_args = { - PORT_ETH, - 0, // starts with ethernet header in line 0 - 0, // filled in from list_line register -}; - -dbsm_t dsp_rx_sm; // the state machine - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; - - -// ---------------------------------------------------------------- - - -#if (FW_SETS_SEQNO) -/* - * Debugging ONLY. This will be handled by the tx_protocol_engine. - * - * This is called when the DSP Rx chain has filled in a packet. - * We set and increment the seqno, then return false, indicating - * that we didn't handle the packet. A bit of a kludge - * but it should work. - */ - -bool -fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false -{ -#if 0 - uint32_t *p = buffer_ram(buf_this); - uint32_t last_line = buffer_pool_status->last_line[buf_this] - sm->last_line_adj; - printf("fw_sets_seqno_inspector: buf_this = %d, last_line = %d\n", - buf_this, last_line); - - print_buffer(p, (last_line + 1)); -#endif - -#if 0 - uint32_t *p = buffer_ram(buf_this); - uint32_t seqno = fw_seqno++; - - // KLUDGE all kinds of nasty magic numbers and embedded knowledge - uint32_t t = p[4]; - t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); - p[4] = t; -#endif - - return false; // we didn't handle the packet -} -#endif - - -inline static void -buffer_irq_handler(unsigned irq) -{ - uint32_t status = buffer_pool_status->status; - - if (0 && (status & ~BPS_IDLE_ALL)){ - putstr("status = "); - puthex32_nl(status); - } - - dbsm_process_status(&dsp_tx_sm, status); - dbsm_process_status(&dsp_rx_sm, status); -} - -int -main(void) -{ - u2_init(); - - output_regs->led_src = 0x3; // h/w controls bottom two bits - clocks_enable_test_clk(true, 1); - - putstr("\neth <-> serdes\n"); - - ethernet_register_link_changed_callback(link_changed_callback); - ethernet_init(); - - // clocks_mimo_config(MC_WE_LOCK_TO_SMA | MC_PROVIDE_CLK_TO_MIMO); - clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO); - -#if 0 - // make bit 15 of Tx gpio's be a s/w output - hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); - hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); -#endif - -#if 1 - output_regs->debug_mux_ctrl = 1; - hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); - hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); -#endif - - - // initialize double buffering state machine for ethernet -> serdes - - dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, - &dsp_tx_recv_args, &dsp_tx_send_args, - eth_pkt_inspector); - - - // initialize double buffering state machine for serdes -> ethernet - - if (FW_SETS_SEQNO){ - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - fw_sets_seqno_inspector); - } - else { - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - dbsm_nop_inspector); - } - - // tell app_common that this dbsm could be sending to the ethernet - ac_could_be_sending_to_eth = &dsp_rx_sm; - - - // kick off the state machines - dbsm_start(&dsp_tx_sm); - dbsm_start(&dsp_rx_sm); - - //int which = 0; - - while(1){ - // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); - // which ^= 0x8000; - - buffer_irq_handler(0); - } -} diff --git a/firmware/microblaze/apps/factory_test.c b/firmware/microblaze/apps/factory_test.c deleted file mode 100644 index e1fbb0e40..000000000 --- a/firmware/microblaze/apps/factory_test.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright 2007,2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "app_common_v2.h" -#include "memcpy_wa.h" -#include -#include -#include -#include -#include -#include -#include "sd.h" - -#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) - -#if (FW_SETS_SEQNO) -static int fw_seqno; // used when f/w is filling in sequence numbers -#endif - - -/* - * Full duplex Tx and Rx between ethernet and DSP pipelines - * - * Buffer 1 is used by the cpu to send frames to the host. - * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow - * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow - */ -//#define CPU_RX_BUF 0 // eth -> cpu - -#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer) -#define DSP_RX_BUF_1 3 // dsp rx -> eth -#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer) -#define DSP_TX_BUF_1 5 // eth -> dsp tx - -/* - * ================================================================ - * configure DSP TX double buffering state machine (eth -> dsp) - * ================================================================ - */ - -// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) -// DSP Tx reads word0 (flags) + timestamp followed by samples - -#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) - -// Receive from ethernet -buf_cmd_args_t dsp_tx_recv_args = { - PORT_ETH, - 0, - BP_LAST_LINE -}; - -// send to DSP Tx -buf_cmd_args_t dsp_tx_send_args = { - PORT_DSP, - DSP_TX_FIRST_LINE, // starts just past transport header - 0 // filled in from last_line register -}; - -dbsm_t dsp_tx_sm; // the state machine - -/* - * ================================================================ - * configure DSP RX double buffering state machine (dsp -> eth) - * ================================================================ - */ - -// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0) -// DSP Rx writes timestamp followed by nlines_per_frame of samples -#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1) - -// receive from DSP -buf_cmd_args_t dsp_rx_recv_args = { - PORT_DSP, - DSP_RX_FIRST_LINE, - BP_LAST_LINE -}; - -// send to ETH -buf_cmd_args_t dsp_rx_send_args = { - PORT_ETH, - 0, // starts with ethernet header in line 0 - 0, // filled in from list_line register -}; - -dbsm_t dsp_rx_sm; // the state machine - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; - - -// variables for streaming mode - -static bool streaming_p = false; -static unsigned int streaming_items_per_frame = 0; -static int streaming_frame_count = 0; -#define FRAMES_PER_CMD 1000 - -bool is_streaming(void){ return streaming_p; } - -// ---------------------------------------------------------------- - - -void -restart_streaming(void) -{ - // setup RX DSP regs - dsp_rx_regs->clear_state = 1; // reset - - streaming_p = true; - streaming_frame_count = FRAMES_PER_CMD; - - dsp_rx_regs->rx_command = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - streaming_items_per_frame, - 1, 1); // set "chain" bit - - // kick off the state machine - dbsm_start(&dsp_rx_sm); - - dsp_rx_regs->rx_time = 0; // enqueue first of two commands - - // make sure this one and the rest have the "now" and "chain" bits set. - dsp_rx_regs->rx_command = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - streaming_items_per_frame, - 1, 1); - - dsp_rx_regs->rx_time = 0; // enqueue second command -} - -void -start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p) -{ - host_mac_addr = *host; // remember who we're sending to - - /* - * Construct ethernet header and word0 and preload into two buffers - */ - u2_eth_packet_t pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.ehdr.dst = *host; - pkt.ehdr.src = *ethernet_mac_addr(); - pkt.ehdr.ethertype = U2_ETHERTYPE; - u2p_set_word0(&pkt.fixed, 0, 0); - // DSP RX will fill in timestamp - - memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt)); - memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt)); - - - if (FW_SETS_SEQNO) - fw_seqno = 0; - - streaming_items_per_frame = p->items_per_frame; - restart_streaming(); -} - - -void -stop_rx_cmd(void) -{ - streaming_p = false; - dsp_rx_regs->clear_state = 1; // flush cmd queue - bp_clear_buf(DSP_RX_BUF_0); - bp_clear_buf(DSP_RX_BUF_1); -} - - -static void -setup_tx() -{ - dsp_tx_regs->clear_state = 1; - bp_clear_buf(DSP_TX_BUF_0); - bp_clear_buf(DSP_TX_BUF_1); - - int tx_scale = 256; - int interp = 32; - - // setup some defaults - - dsp_tx_regs->freq = 0; - dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; - dsp_tx_regs->interp_rate = interp; -} - - -#if (FW_SETS_SEQNO) -/* - * Debugging ONLY. This will be handled by the tx_protocol_engine. - * - * This is called when the DSP Rx chain has filled in a packet. - * We set and increment the seqno, then return false, indicating - * that we didn't handle the packet. A bit of a kludge - * but it should work. - */ -bool -fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false -{ - uint32_t *p = buffer_ram(buf_this); - uint32_t seqno = fw_seqno++; - - // KLUDGE all kinds of nasty magic numbers and embedded knowledge - uint32_t t = p[4]; - t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); - p[4] = t; - - // queue up another rx command when required - if (streaming_p && --streaming_frame_count == 0){ - streaming_frame_count = FRAMES_PER_CMD; - dsp_rx_regs->rx_time = 0; - } - - return false; // we didn't handle the packet -} -#endif - - -inline static void -buffer_irq_handler(unsigned irq) -{ - uint32_t status = buffer_pool_status->status; - - dbsm_process_status(&dsp_tx_sm, status); - dbsm_process_status(&dsp_rx_sm, status); -} - -int test_ram() -{ - int i,j,k; - output_regs->ram_page = 1<<10; - - extram[0] = 0xDEADBEEF; - extram[1] = 0xF00D1234; - extram[7] = 0x76543210; - - output_regs->ram_page = 2<<10; - extram[7] = 0x55555555; - extram[1] = 0xaaaaaaaa; - extram[0] = 0xeeeeeeee; - - output_regs->ram_page = 1<<10; - - i = extram[0]; - k = extram[1]; - j = extram[7]; - - if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { - puts("RAM FAIL1!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - - output_regs->ram_page = 2<<10; - - j = extram[7]; - k = extram[1]; - i = extram[0]; - - if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { - puts("RAM FAIL2!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - return 1; -} - -int test_sd() -{ - int i = sd_init(); - if(i==0) { - puts("FAILED INIT of Card\n"); - return 0; - } - - unsigned char buf[512]; - i = sd_read_block(2048,buf); - if(i == 0) { - puts("READ Command Rejected\n"); - return 0; - } - if((buf[0]==0xb8)&&(buf[1]==0x08)&&(buf[2]==0x00)&&(buf[3]==0x50)) - ; - else { - puts("Read bad data from SD Card\n"); - return 0; - } - return 1; -} - -int -main(void) -{ - u2_init(); - - putstr("\nFactory Test\n"); - - print_mac_addr(ethernet_mac_addr()->addr); - newline(); - - if(test_sd()) - puts("SD OK\n"); - else { - puts("SD FAIL\n"); - // hal_finish(); - //return 0; - } - if(test_ram()) - puts("RAM OK\n"); - else { - puts("RAM FAIL\n"); - hal_finish(); - return 0; - } - - print_mac_addr(ethernet_mac_addr()->addr); - newline(); - - output_regs->led_src = 0x7; // make bottom 3 controlled by HW - - ethernet_register_link_changed_callback(link_changed_callback); - ethernet_init(); - - clocks_enable_tx_dboard(true,1); - clocks_mimo_config(MC_WE_LOCK_TO_SMA); -#if 0 - // make bit 15 of Tx gpio's be a s/w output - hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); - hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); -#endif - - output_regs->debug_mux_ctrl = 1; -#if 0 - hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); - hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); -#endif - - - // initialize double buffering state machine for ethernet -> DSP Tx - - dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, - &dsp_tx_recv_args, &dsp_tx_send_args, - eth_pkt_inspector); - - - // initialize double buffering state machine for DSP RX -> Ethernet - - if (FW_SETS_SEQNO){ - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - fw_sets_seqno_inspector); - } - else { - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - dbsm_nop_inspector); - } - - // tell app_common that this dbsm could be sending to the ethernet - ac_could_be_sending_to_eth = &dsp_rx_sm; - - - // program tx registers - setup_tx(); - - // kick off the state machine - dbsm_start(&dsp_tx_sm); - - //int which = 0; - - while(1){ - // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); - // which ^= 0x8000; - - buffer_irq_handler(0); - - int pending = pic_regs->pending; // poll for under or overrun - - if (pending & PIC_UNDERRUN_INT){ - dbsm_handle_tx_underrun(&dsp_tx_sm); - pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt - putchar('U'); - } - - if (pending & PIC_OVERRUN_INT){ - dbsm_handle_rx_overrun(&dsp_rx_sm); - pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt - - // FIXME Figure out how to handle this robustly. - // Any buffers that are emptying should be allowed to drain... - - if (streaming_p){ - // restart_streaming(); - // FIXME report error - } - else { - // FIXME report error - } - putchar('O'); - } - } -} diff --git a/firmware/microblaze/apps/gen_eth_packets.c b/firmware/microblaze/apps/gen_eth_packets.c deleted file mode 100644 index 4d521f6bf..000000000 --- a/firmware/microblaze/apps/gen_eth_packets.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "memcpy_wa.h" -#include "print_rmon_regs.h" -#include -#include -#include - - -// ---------------------------------------------------------------- - -static eth_mac_addr_t dst_mac_addr = - {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}; - -// ---------------------------------------------------------------- - -// #define PACKET_SIZE 1500 // bytes -// #define ETH_DATA_RATE 1000000 // 1MB/s -// #define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s - -// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE; // ticks between interrupts - -static int timer_delta = (int)(MASTER_CLK_RATE * 1e-3); // tick at 1 kHz -static int sim_timer_delta = (int)(MASTER_CLK_RATE * 100e-6); // tick at 10 kHz - -static volatile bool send_packet_now = false; // timer handler sets this -static volatile bool link_is_up = false; // eth handler sets this - -int packet_number = 0; - - -#define CPU_TX_BUF 0 // cpu xmits ethernet frames from here -#define CPU_RX_BUF 1 // receive ethernet frames here - -// ---------------------------------------------------------------- - -/* - * Called when eth phy state changes (w/ interrupts disabled) - */ -void -link_changed_callback(int speed) -{ - link_is_up = speed == 0 ? false : true; - hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2); - printf("\neth link changed: speed = %d\n", speed); -} - -void -timer_irq_handler(unsigned irq) -{ - hal_set_timeout(timer_delta); // schedule next timeout - send_packet_now = 1; -} - - -static void -init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum) -{ - int i = 0; - int mark = ((bufnum & 0xff) << 24) | 0x005A0000; - - for (i = 0; i < BP_NLINES; i++){ - buf[i] = mark | i; - mark ^= 0x00FF0000; - } - - // copy header into buffer - memcpy_wa(buf, pkt, sizeof(*pkt)); -} - -static void -init_packets(void) -{ - u2_eth_packet_t pkt __attribute__((aligned (4))); - - memset(&pkt, 0, sizeof(pkt)); - - pkt.ehdr.dst = dst_mac_addr; - pkt.ehdr.src = *ethernet_mac_addr(); - pkt.ehdr.ethertype = U2_ETHERTYPE; - pkt.fixed.word0 = 0x01234567; - pkt.fixed.timestamp = 0xffffffff; - - // init just the one we're using - init_packet((void *)buffer_ram(CPU_TX_BUF), &pkt, CPU_TX_BUF); -} - -int -main(void) -{ - int npackets_sent = 0; - - u2_init(); - - // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output - //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - - putstr("\ngen_eth_packets\n"); - - hal_set_leds(0x0, 0x3); - - init_packets(); - - pic_register_handler(IRQ_TIMER, timer_irq_handler); - - if (hwconfig_simulation_p()) - timer_delta = sim_timer_delta; - - hal_set_timeout(timer_delta); - - ethernet_register_link_changed_callback(link_changed_callback); - ethernet_init(); - - /* - if (hwconfig_simulation_p()){ - eth_mac->speed = 4; // hardcode mac speed to 1000 - link_is_up = true; - } - */ - - // fire off a receive from the ethernet - bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE); - - while(1){ - uint32_t status = buffer_pool_status->status; - - if (status & (BPS_DONE(CPU_RX_BUF) | BPS_ERROR(CPU_RX_BUF))){ - bp_clear_buf(CPU_RX_BUF); - // ignore incoming ethernet packets; they were looped back in sim - bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE); - } - - if (status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))){ - if (status & BPS_ERROR(CPU_TX_BUF)){ - putchar('E'); - } - bp_clear_buf(CPU_TX_BUF); - npackets_sent++; - if ((npackets_sent & 0xF) == 0){ // print after every 16 packets - //print_rmon_regs(); - putchar('.'); - } - } - - if (link_is_up && send_packet_now && (status & BPS_IDLE(CPU_TX_BUF))){ - send_packet_now = false; - - // kick off the next packet - // FIXME set packet number in packet - - bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, 255); // 1KB total - hal_toggle_leds(0x1); - } - } - - hal_finish(); - return 1; -} diff --git a/firmware/microblaze/apps/gen_pause_frames.c b/firmware/microblaze/apps/gen_pause_frames.c deleted file mode 100644 index 0f81dafff..000000000 --- a/firmware/microblaze/apps/gen_pause_frames.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "u2_eth_packet.h" -#include "memcpy_wa.h" -#include -#include - - -// ---------------------------------------------------------------- - -unsigned char dst_mac_addr[6] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -// ---------------------------------------------------------------- - -// #define PACKET_SIZE 1500 // bytes -// #define ETH_DATA_RATE 1000000 // 1MB/s -// #define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s - -// static int timer_delta = MASTER_CLK_RATE/ETH_PACKET_RATE; // ticks between interrupts - -static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz - -static volatile bool send_packet_now = false; // timer handler sets this -static volatile bool link_is_up = false; // eth handler sets this - -int packet_number = 0; - -// ---------------------------------------------------------------- - -// debugging output on tx pins -#define LS_MASK 0xE0000 -#define LS_1000 0x80000 -#define LS_100 0x40000 -#define LS_10 0x20000 - - -/* - * Called when eth phy state changes (w/ interrupts disabled) - */ -void -link_changed_callback(int speed) -{ - int v = 0; - switch(speed){ - case 10: - v = LS_10; - link_is_up = true; - break; - - case 100: - v = LS_100; - link_is_up = true; - break; - - case 1000: - v = LS_100; - link_is_up = true; - break; - - default: - v = 0; - link_is_up = false; - break; - } - - hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */ - - putstr("\neth link changed: speed = "); - puthex16_nl(speed); -} - -void -timer_irq_handler(unsigned irq) -{ - hal_set_timeout(timer_delta); // schedule next timeout - send_packet_now = 1; -} - - -void -buffer_irq_handler(unsigned irq) -{ - // FIXME -} - -static void -init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum) -{ - int i = 0; - int mark = ((bufnum & 0xff) << 24) | 0x005A0000; - - for (i = 0; i < BP_NLINES; i++){ - buf[i] = mark | i; - mark ^= 0x00FF0000; - } - - // copy header into buffer - memcpy_wa(buf, pkt, sizeof(*pkt)); -} - -static void -init_packets(void) -{ - int i; - - u2_eth_packet_t pkt __attribute__((aligned (4))); - - for (i = 0; i < 6; i++){ - pkt.ehdr.dst.addr[i] = dst_mac_addr[i]; - } - pkt.ehdr.src = *ethernet_mac_addr(); - pkt.ehdr.ethertype = U2_ETHERTYPE; - - // fill ALL buffers for debugging - for (i = 0; i < 8; i++) - init_packet((void *)buffer_ram(i), &pkt, i); -} - -static int led_counter = 0; - -int -main(void) -{ - int send_pause = 1; - - u2_init(); - - // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output - //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - - putstr("\ngen_eth_packets\n"); - - // Control LEDs - output_regs->leds = 0x00; - - init_packets(); - - // pic_register_handler(IRQ_BUFFER, buffer_irq_handler); // poll for now - pic_register_handler(IRQ_TIMER, timer_irq_handler); - hal_set_timeout(timer_delta); - - ethernet_register_link_changed_callback(link_changed_callback); - - ethernet_init(); - - eth_mac->pause_frame_send_en = 1; - eth_mac->pause_quanta_set = 16384 / 512; - - // eth_mac->speed = 4; // FIXME hardcode mac speed to 1000 - - while(1){ - if (link_is_up && send_packet_now){ - send_packet_now = false; - - - if (send_pause) - eth_mac->xon_cpu = 1; - else - eth_mac->xon_cpu = 0; - - send_pause ^= 1; - - // kick off the next packet - // FIXME set packet number in packet - -#if 0 - bp_send_from_buf(0, PORT_ETH, 1, 0, 255); // 1KB total - - while ((buffer_pool_status->status & (BPS_DONE_0|BPS_ERROR_0)) == 0) - ; - bp_clear_buf(0); -#endif - - output_regs->leds = ((++led_counter) & 0x1) | (link_is_up ? 0x2 : 0x0); - } - } - - hal_finish(); - return 1; -} diff --git a/firmware/microblaze/apps/hello.c b/firmware/microblaze/apps/hello.c deleted file mode 100644 index bce843093..000000000 --- a/firmware/microblaze/apps/hello.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#include "u2_init.h" -#include "stdio.h" - -int -main(void) -{ - u2_init(); - - puts("Hello World"); - puts("Goodbye World"); - - return 0; -} diff --git a/firmware/microblaze/apps/ibs_rx_test.c b/firmware/microblaze/apps/ibs_rx_test.c deleted file mode 100644 index bdc04747e..000000000 --- a/firmware/microblaze/apps/ibs_rx_test.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "nonstdio.h" - -#define PORT 2 // ethernet = 2, serdes = 0 -int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf; -int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle; - -int buffer_state[4]; - -static void __attribute__((unused)) -wait_until_status_nonzero(void) -{ - while (buffer_pool_status->status == 0) - ; -} - -int -main(void) -{ - int i; - - u2_init(); - - output_regs->adc_ctrl = 0x0A; - - dsp_rx_regs->freq = 0; - dsp_rx_regs->scale_iq = (1 << 16) | 1; - dsp_rx_regs->decim_rate = 8; - - volatile unsigned int *buffer0 = buffer_ram(0); - volatile unsigned int *buffer1 = buffer_ram(1); - volatile unsigned int *buffer2 = buffer_ram(2); - - putstr("Starting RX\n"); - bp_clear_buf(0); - bp_receive_to_buf(0, 1, 1, 0, 99); - - dsp_rx_regs->rx_command = (50 << 9) | 100; // Numlines, lines per frame - dsp_rx_regs->rx_time = 0x2000; - - dsp_rx_regs->rx_command = (137 << 9) | 50; // Numlines, lines per frame - dsp_rx_regs->rx_time = 0x2200; - - while (buffer_pool_status->status == 0) - ; - bp_clear_buf(0); - bp_clear_buf(1); - bp_receive_to_buf(1, 1, 1, 0, 99); - while (buffer_pool_status->status == 0) - ; - bp_clear_buf(2); - bp_receive_to_buf(2, 1, 1, 0, 99); - while (buffer_pool_status->status == 0) - ; - - for(i=0;i<100;i++) { - puthex(i); - putstr(" "); - puthex_nl(buffer0[i]); - } - for(i=0;i<60;i++) { - puthex(i); - putstr(" "); - puthex_nl(buffer1[i]); - } - for(i=0;i<60;i++) { - puthex(i); - putstr(" "); - puthex_nl(buffer2[i]); - } - //while(timer_regs -> time < 0x6000) - // {} - - putstr("Done\n"); - hal_finish(); - - return 1; -} diff --git a/firmware/microblaze/apps/ibs_tx_test.c b/firmware/microblaze/apps/ibs_tx_test.c deleted file mode 100644 index ff9446d92..000000000 --- a/firmware/microblaze/apps/ibs_tx_test.c +++ /dev/null @@ -1,160 +0,0 @@ -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "nonstdio.h" - -// Globals -#define EMPTY 0 -#define FILLING 1 -#define FULL 2 -#define EMPTYING 3 - -#define PORT 2 // ethernet = 2, serdes = 0 -int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf; -int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle; - -int buffer_state[4]; - -static void -wait_until_status_nonzero(void) -{ - while (buffer_pool_status->status == 0) - ; -} - -int -main(void) -{ - int i; - - u2_init(); - - dsp_tx_regs->freq = 0; - dsp_tx_regs->scale_iq = (1 << 16) | 1; - dsp_tx_regs->interp_rate = 8; - - // Write data to be sent into the first buffer - volatile unsigned int *buffer0 = buffer_ram(0); - volatile unsigned int *buffer1 = buffer_ram(1); - - - putstr("Starting to fill in RAM\n"); - for(i=0;i<512;i++) - buffer0[i] = i; - putstr("Filled in RAM\n"); - - buffer0[0] = 7; // start and end of buffer, send immediately - buffer0[1] = 0x0000; // start time - bp_clear_buf(0); - bp_send_from_buf(0, 1, 1, 0, 9); - while (buffer_pool_status->status == 0) - ; - while(timer_regs -> time < 0x6000) - {} - - buffer0[0] = 3; // start and end of buffer - buffer0[1] = 0x8000; // start time - bp_clear_buf(0); - bp_send_from_buf(0, 1, 1, 0, 9); - while (buffer_pool_status->status == 0) - ; - while(timer_regs -> time < 0x8400) - {} - - buffer0[0] = 3; // start and end of buffer - buffer0[1] = 0x8800; // start time - bp_clear_buf(0); - bp_send_from_buf(0, 1, 1, 0, 9); - while (buffer_pool_status->status == 0) - ; - while(timer_regs -> time < 0x9000) - {} - - buffer0[0] = 0x2; // not last - buffer0[1] = 0x9100; // start time - bp_clear_buf(0); - bp_send_from_buf(0, 1, 1, 0, 9); - while (buffer_pool_status->status == 0) - ; - buffer0[0] = 0x1; // last - buffer0[1] = 0x0000; // start time - bp_clear_buf(0); - bp_send_from_buf(0, 1, 1, 0, 9); - while (buffer_pool_status->status == 0) - ; - - - buffer0[0] = 0x3; // first and last - buffer0[1] = 0x8000; // Time in the past - bp_clear_buf(0); - bp_send_from_buf(0, 1, 1, 0, 9); - while (buffer_pool_status->status == 0) - ; - - /* - buffer0[0] = 0x2; // not last - buffer0[1] = 0x9600; // start time - bp_clear_buf(0); - bp_send_from_buf(0, 1, 1, 0, 9); - while (buffer_pool_status->status == 0) - ; - */ - - while(timer_regs -> time < 0xa000) - {} - - putstr("Done\n"); - - while(1) - {} - hal_finish(); - - // Send a bunch, let them pile up in FIFO - bp_send_from_buf(0, 2, 1, 21, 80); wait_until_status_nonzero(); - bp_clear_buf(0); - putstr("First add'l TX done\n"); - bp_send_from_buf(0, 2, 1, 81, 288); wait_until_status_nonzero(); - bp_clear_buf(0); - bp_send_from_buf(0, 2, 1, 289, 292); wait_until_status_nonzero(); - bp_clear_buf(0); - bp_send_from_buf(0, 2, 1, 293, 326); wait_until_status_nonzero(); - bp_clear_buf(0); - bp_send_from_buf(0, 2, 1, 327, 399); wait_until_status_nonzero(); - bp_clear_buf(0); - bp_send_from_buf(0, 2, 1, 400, 511); wait_until_status_nonzero(); - bp_clear_buf(0); - putstr("All add'l TX done\n"); - - bp_receive_to_buf(1, 2, 1, 21, 80); wait_until_status_nonzero(); - bp_clear_buf(1); - putstr("First add'l RX done\n"); - bp_receive_to_buf(1, 2, 1, 81, 288); wait_until_status_nonzero(); - bp_clear_buf(1); - bp_receive_to_buf(1, 2, 1, 289, 292); wait_until_status_nonzero(); - bp_clear_buf(1); - bp_receive_to_buf(1, 2, 1, 293, 326); wait_until_status_nonzero(); - bp_clear_buf(1); - bp_receive_to_buf(1, 2, 1, 327, 399); wait_until_status_nonzero(); - bp_clear_buf(1); - bp_receive_to_buf(1, 2, 1, 400, 511); wait_until_status_nonzero(); - bp_clear_buf(1); - putstr("All add'l RX done\n"); - - for(i=0;i<512;i++) - if(buffer0[i] != buffer1[i]) { - putstr("ERROR at location: "); - puthex_nl(i); - putstr("Value sent: "); - puthex_nl(buffer0[i]); - putstr("Value rcvd: "); - puthex_nl(buffer1[i]); - //break; - } - - putstr("Done Testing\n"); - - hal_finish(); - return 1; -} diff --git a/firmware/microblaze/apps/mimo_app_common_v2.c b/firmware/microblaze/apps/mimo_app_common_v2.c deleted file mode 100644 index 5dbecb0d0..000000000 --- a/firmware/microblaze/apps/mimo_app_common_v2.c +++ /dev/null @@ -1,582 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008,2009 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "mimo_app_common_v2.h" -#include "buffer_pool.h" -#include "memcpy_wa.h" -#include "ethernet.h" -#include "nonstdio.h" -#include "print_rmon_regs.h" -#include "db.h" -#include "db_base.h" -#include "clocks.h" -#include "u2_init.h" -#include - -volatile bool link_is_up = false; // eth handler sets this -int cpu_tx_buf_dest_port = PORT_ETH; - -// If this is non-zero, this dbsm could be writing to the ethernet -dbsm_t *ac_could_be_sending_to_eth; - -static unsigned char exp_seqno __attribute__((unused)) = 0; - -void abort(void); - -static bool -burn_mac_addr(const op_burn_mac_addr_t *p) -{ - return ethernet_set_mac_addr(&p->addr); -} - -static bool -sync_to_pps(const op_generic_t *p) -{ - timesync_regs->sync_on_next_pps = 1; - putstr("SYNC to PPS\n"); - return true; -} - -static bool -config_mimo_cmd(const op_config_mimo_t *p) -{ - clocks_mimo_config(p->flags); - return true; -} - -void -set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt) -{ - reply_pkt->ehdr.dst = cmd_pkt->ehdr.src; - reply_pkt->ehdr.src = *ethernet_mac_addr(); - reply_pkt->ehdr.ethertype = U2_ETHERTYPE; - reply_pkt->thdr.flags = 0; - reply_pkt->thdr.fifo_status = 0; // written by protocol engine - reply_pkt->thdr.seqno = 0; // written by protocol engine - reply_pkt->thdr.ack = 0; // written by protocol engine - u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN); - reply_pkt->fixed.timestamp = timer_regs->time; -} - -static void -send_reply(unsigned char *reply, size_t reply_len) -{ - if (reply_len < 64) - reply_len = 64; - - // wait for buffer to become idle - hal_set_leds(0x4, 0x4); - while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0) - ; - hal_set_leds(0x0, 0x4); - - // copy reply into CPU_TX_BUF - memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len); - - // wait until nobody else is sending to the ethernet - if (ac_could_be_sending_to_eth){ - hal_set_leds(0x8, 0x8); - dbsm_wait_for_opening(ac_could_be_sending_to_eth); - hal_set_leds(0x0, 0x8); - } - - if (0){ - printf("sending_reply to port %d, len = %d\n", cpu_tx_buf_dest_port, (int)reply_len); - print_buffer(buffer_ram(CPU_TX_BUF), reply_len/4); - } - - // fire it off - bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 1, 0, reply_len/4); - - // wait for it to complete (not long, it's a small pkt) - while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0) - ; - - bp_clear_buf(CPU_TX_BUF); -} - - -static size_t -op_id_cmd(const op_generic_t *p, - void *reply_payload, size_t reply_payload_space) -{ - op_id_reply_t *r = (op_id_reply_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) // no room - return 0; - - // Build reply subpacket - - r->opcode = OP_ID_REPLY; - r->len = sizeof(op_id_reply_t); - r->rid = p->rid; - r->addr = *ethernet_mac_addr(); - r->hw_rev = (u2_hw_rev_major << 8) | u2_hw_rev_minor; - // r->fpga_md5sum = ; // FIXME - // r->sw_md5sum = ; // FIXME - - return r->len; -} - - -static size_t -config_tx_v2_cmd(const op_config_tx_v2_t *p, - void *reply_payload, size_t reply_payload_space) -{ - op_config_tx_reply_v2_t *r = (op_config_tx_reply_v2_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) - return 0; // no room - - struct tune_result tune_result; - memset(&tune_result, 0, sizeof(tune_result)); - - bool ok = true; - -#if 0 - if (p->valid & CFGV_GAIN){ - ok &= db_set_gain(tx_dboard, p->gain); - } - - if (p->valid & CFGV_FREQ){ - bool was_streaming = is_streaming(); - if (was_streaming) - stop_rx_cmd(); - - u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo); - bool tune_ok = db_tune(tx_dboard, f, &tune_result); - ok &= tune_ok; - print_tune_result("Tx", tune_ok, f, &tune_result); - - if (was_streaming) - restart_streaming(); - } - - if (p->valid & CFGV_INTERP_DECIM){ - int interp = p->interp; - int hb1 = 0; - int hb2 = 0; - - if (!(interp & 1)){ - hb2 = 1; - interp = interp >> 1; - } - - if (!(interp & 1)){ - hb1 = 1; - interp = interp >> 1; - } - - if (interp < MIN_CIC_INTERP || interp > MAX_CIC_INTERP) - ok = false; - else { - dsp_tx_regs->interp_rate = (hb1<<9) | (hb2<<8) | interp; - // printf("Interp: %d, register %d\n", p->interp, (hb1<<9) | (hb2<<8) | interp); - } - } - - if (p->valid & CFGV_SCALE_IQ){ - dsp_tx_regs->scale_iq = p->scale_iq; - } -#endif - - // Build reply subpacket - - r->opcode = OP_CONFIG_TX_REPLY_V2; - r->len = sizeof(*r); - r->rid = p->rid; - r->ok = ok; - r->inverted = tune_result.inverted; - r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq); - r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq); - r->duc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq); - r->duc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq); - r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq); - r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq); - return r->len; -} - -static size_t -config_rx_v2_cmd(const op_config_rx_v2_t *p, - void *reply_payload, size_t reply_payload_space) -{ - op_config_rx_reply_v2_t *r = (op_config_rx_reply_v2_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) - return 0; // no room - - struct tune_result tune_result; - memset(&tune_result, 0, sizeof(tune_result)); - - bool ok = true; - - if (p->valid & CFGV_GAIN){ - ok &= db_set_gain(rx_dboard, p->gain); - } - - if (p->valid & CFGV_FREQ){ - bool was_streaming = is_streaming(); - if (was_streaming) - stop_rx_cmd(); - - u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo); - bool tune_ok = db_tune(rx_dboard, f, &tune_result); - ok &= tune_ok; - print_tune_result("Rx", tune_ok, f, &tune_result); - - if (was_streaming) - restart_streaming(); - } - - if (p->valid & CFGV_INTERP_DECIM){ - int decim = p->decim; - int hb1 = 0; - int hb2 = 0; - - if(!(decim & 1)) { - hb2 = 1; - decim = decim >> 1; - } - - if(!(decim & 1)) { - hb1 = 1; - decim = decim >> 1; - } - - if (decim < MIN_CIC_DECIM || decim > MAX_CIC_DECIM) - ok = false; - else { - dsp_rx_regs->decim_rate = (hb1<<9) | (hb2<<8) | decim; - // printf("Decim: %d, register %d\n", p->decim, (hb1<<9) | (hb2<<8) | decim); - } - } - - if (p->valid & CFGV_SCALE_IQ){ - dsp_rx_regs->scale_iq = p->scale_iq; - } - - // Build reply subpacket - - r->opcode = OP_CONFIG_RX_REPLY_V2; - r->len = sizeof(*r); - r->rid = p->rid; - r->ok = ok; - r->inverted = tune_result.inverted; - r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq); - r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq); - r->ddc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq); - r->ddc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq); - r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq); - r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq); - - return r->len; -} - -static size_t -read_time_cmd(const op_generic_t *p, - void *reply_payload, size_t reply_payload_space) -{ - op_read_time_reply_t *r = (op_read_time_reply_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) - return 0; // no room - - r->opcode = OP_READ_TIME_REPLY; - r->len = sizeof(*r); - r->rid = p->rid; - r->time = timer_regs->time; - - return r->len; -} - -static void -fill_db_info(u2_db_info_t *p, const struct db_base *db) -{ - p->dbid = db->dbid; - p->freq_min_hi = u2_fxpt_freq_hi(db->freq_min); - p->freq_min_lo = u2_fxpt_freq_lo(db->freq_min); - p->freq_max_hi = u2_fxpt_freq_hi(db->freq_max); - p->freq_max_lo = u2_fxpt_freq_lo(db->freq_max); - p->gain_min = db->gain_min; - p->gain_max = db->gain_max; - p->gain_step_size = db->gain_step_size; -} - -static size_t -dboard_info_cmd(const op_generic_t *p, - void *reply_payload, size_t reply_payload_space) -{ - op_dboard_info_reply_t *r = (op_dboard_info_reply_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) - return 0; // no room - - r->opcode = OP_DBOARD_INFO_REPLY; - r->len = sizeof(*r); - r->rid = p->rid; - r->ok = true; - - fill_db_info(&r->tx_db_info, tx_dboard); - fill_db_info(&r->rx_db_info, rx_dboard); - - return r->len; -} - -static size_t -peek_cmd(const op_peek_t *p, - void *reply_payload, size_t reply_payload_space) -{ - op_generic_t *r = (op_generic_t *) reply_payload; - - putstr("peek: addr="); puthex32(p->addr); - printf(" bytes=%u\n", p->bytes); - - if ((reply_payload_space < (sizeof(*r) + p->bytes)) || - p->bytes > MAX_SUBPKT_LEN - sizeof(op_generic_t)) { - putstr("peek: insufficient reply packet space\n"); - return 0; // FIXME do partial read? - } - - r->opcode = OP_PEEK_REPLY; - r->len = sizeof(*r)+p->bytes; - r->rid = p->rid; - r->ok = true; - - memcpy_wa(reply_payload+sizeof(*r), (void *)p->addr, p->bytes); - - return r->len; -} - -static bool -poke_cmd(const op_poke_t *p) -{ - int bytes = p->len - sizeof(*p); - putstr("poke: addr="); puthex32(p->addr); - printf(" bytes=%u\n", bytes); - - uint8_t *src = (uint8_t *)p + sizeof(*p); - memcpy_wa((void *)p->addr, src, bytes); - - return true; -} - -static size_t -generic_reply(const op_generic_t *p, - void *reply_payload, size_t reply_payload_space, - bool ok) -{ - op_generic_t *r = (op_generic_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) - return 0; // no room - - r->opcode = p->opcode | OP_REPLY_BIT; - r->len = sizeof(*r); - r->rid = p->rid; - r->ok = ok; - - return r->len; -} - -static size_t -add_eop(void *reply_payload, size_t reply_payload_space) -{ - op_generic_t *r = (op_generic_t *) reply_payload; - if (reply_payload_space < sizeof(*r)) - return 0; // no room - - r->opcode = OP_EOP; - r->len = sizeof(*r); - r->rid = 0; - r->ok = 0; - - return r->len; -} - -void -handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len) -{ - unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4; - unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)]; - int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t); - - // initialize reply - memset(reply, 0, sizeof(reply)); - set_reply_hdr((u2_eth_packet_t *) reply, pkt); - - // point to beginning of payload (subpackets) - unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t); - int payload_len = len - sizeof(u2_eth_packet_t); - - size_t subpktlen = 0; - - while (payload_len >= sizeof(op_generic_t)){ - const op_generic_t *gp = (const op_generic_t *) payload; - subpktlen = 0; - - // printf("\nopcode = %d\n", gp->opcode); - - switch(gp->opcode){ - case OP_EOP: // end of subpackets - goto end_of_subpackets; - - case OP_ID: - subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space); - break; - - case OP_CONFIG_TX_V2: - subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload, - reply_payload, reply_payload_space); - break; - - case OP_CONFIG_RX_V2: - subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload, - reply_payload, reply_payload_space); - break; - - case OP_START_RX_STREAMING: - start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload); - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true); - break; - - case OP_STOP_RX: - stop_rx_cmd(); - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true); - break; - - case OP_BURN_MAC_ADDR: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - burn_mac_addr((op_burn_mac_addr_t *) payload)); - break; - - case OP_CONFIG_MIMO: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - config_mimo_cmd((op_config_mimo_t *) payload)); - break; - - case OP_READ_TIME: - subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space); - break; - - case OP_DBOARD_INFO: - subpktlen = dboard_info_cmd(gp, reply_payload, reply_payload_space); - break; - - case OP_SYNC_TO_PPS: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - sync_to_pps((op_generic_t *) payload)); - break; - - case OP_PEEK: - subpktlen = peek_cmd((op_peek_t *)payload, reply_payload, reply_payload_space); - break; - - case OP_POKE: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - poke_cmd((op_poke_t *)payload)); - break; - - default: - printf("app_common_v2: unhandled opcode = %d\n", gp->opcode); - break; - } - - int t = (gp->len + 3) & ~3; // bump to a multiple of 4 - payload += t; - payload_len -= t; - - subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4 - reply_payload += subpktlen; - reply_payload_space -= subpktlen; - } - - end_of_subpackets: - - // add the EOP marker - subpktlen = add_eop(reply_payload, reply_payload_space); - subpktlen = (subpktlen + 3) & ~3; // bump to a multiple of 4 - reply_payload += subpktlen; - reply_payload_space -= subpktlen; - - send_reply(reply, reply_payload - reply); -} - - -/* - * Called when an ethernet packet is received. - * Return true if we handled it here, otherwise - * it'll be passed on to the DSP Tx pipe - */ -int -eth_pkt_inspector(bsm12_t *sm, int bufno) -{ - u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno); - size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4; - - //static size_t last_len = 0; - - // hal_toggle_leds(0x1); - - // inspect rcvd frame and figure out what do do. - - if (pkt->ehdr.ethertype != U2_ETHERTYPE) - return true; // ignore, probably bogus PAUSE frame from MAC - - int chan = u2p_chan(&pkt->fixed); - - switch (chan){ - case CONTROL_CHAN: - handle_control_chan_frame(pkt, byte_len); - return -1; - break; - - case 0: - return 0; // pass it off to DSP TX - - case 1: - return 1; // pass it off to SERDES TX - - default: - abort(); - break; - } -} - -/* - * Called when eth phy state changes (w/ interrupts disabled) - */ -void -link_changed_callback(int speed) -{ - link_is_up = speed != 0; - hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45); - printf("\neth link changed: speed = %d\n", speed); -} - - -void -print_tune_result(char *msg, bool tune_ok, - u2_fxpt_freq_t target_freq, struct tune_result *r) -{ -#if 0 - printf("db_tune %s %s\n", msg, tune_ok ? "true" : "false"); - putstr(" target_freq "); print_fxpt_freq(target_freq); newline(); - putstr(" baseband_freq "); print_fxpt_freq(r->baseband_freq); newline(); - putstr(" dxc_freq "); print_fxpt_freq(r->dxc_freq); newline(); - putstr(" residual_freq "); print_fxpt_freq(r->residual_freq); newline(); - printf(" inverted %s\n", r->inverted ? "true" : "false"); -#endif -} diff --git a/firmware/microblaze/apps/mimo_app_common_v2.h b/firmware/microblaze/apps/mimo_app_common_v2.h deleted file mode 100644 index 1e62ced37..000000000 --- a/firmware/microblaze/apps/mimo_app_common_v2.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 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, see . - */ - -#ifndef INCLUDED_APP_COMMON_H -#define INCLUDED_APP_COMMON_H - -#include -#include "usrp2_eth_packet.h" -#include "bsm12.h" -#include "memory_map.h" -#include "hal_io.h" -#include -#include - -#define CPU_TX_BUF 7 // cpu -> eth - -#define _AL4 __attribute__((aligned (4))) - -extern volatile bool link_is_up; // eth handler sets this - -// If there's a dbsm that sends to the ethernet, put it's address here -extern dbsm_t *ac_could_be_sending_to_eth; - -extern int cpu_tx_buf_dest_port; - -void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt); - -/* - * Called when an ethernet packet is received. - */ -int eth_pkt_inspector(bsm12_t *sm, int bufno); - - -void link_changed_callback(int speed); - -void -print_tune_result(char *msg, bool tune_ok, - u2_fxpt_freq_t target_freq, struct tune_result *r); - - -void start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p); -void stop_rx_cmd(void); -void restart_streaming(void); -bool is_streaming(void); - -void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len); - -#endif /* INCLUDED_APP_COMMON_H */ diff --git a/firmware/microblaze/apps/mimo_tx.c b/firmware/microblaze/apps/mimo_tx.c deleted file mode 100644 index e0f8aa6fa..000000000 --- a/firmware/microblaze/apps/mimo_tx.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright 2007,2008,2009 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, see . - */ - -/* - * This is a down and dirty test program that confirms that the we can - * coherently transmit different signals to two USRP2s connected via a - * mimo cable. This code runs in the USRP2 connected to the ethernet. - * The other USRP runs mimo_tx_slave. The host runs test_mimo_tx. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "bsm12.h" -#include "mimo_app_common_v2.h" -#include "memcpy_wa.h" -#include -#include -#include -#include "clocks.h" - -#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) - -#if (FW_SETS_SEQNO) -static int fw_seqno; // used when f/w is filling in sequence numbers -#endif - - -/* - * Experimental code to transmit packets to DSP Tx and SERDES - * - * Hard wire the Tx config so we don't have to deal with control stuff yet. - */ - -#define BUF_BSM12_0 4 -#define BUF_BSM12_1 5 -#define BUF_BSM12_2 6 - -//#define CPU_TX_BUF 7 // cpu -> eth - -// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) -// DSP Tx reads word0 (flags) + timestamp followed by samples - -#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) - -// Receive from ethernet -buf_cmd_args_t bsm12_recv_args = { - PORT_ETH, - 0, - BP_LAST_LINE -}; - -// send to DSP Tx -buf_cmd_args_t bsm12_send0_args = { - PORT_DSP, - DSP_TX_FIRST_LINE, // starts just past transport header - 0 // filled in from last_line register -}; - -// send to SERDES -buf_cmd_args_t bsm12_send1_args = { - PORT_SERDES, - 0, // starts just past transport header - 0 // filled in from last_line register -}; - -bsm12_t bsm12_sm; // the state machine - -#if 0 -/* - * ================================================================ - * configure DSP RX double buffering state machine (dsp -> eth) - * ================================================================ - */ - -// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0) -// DSP Rx writes timestamp followed by nlines_per_frame of samples -#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1) - -// receive from DSP -buf_cmd_args_t dsp_rx_recv_args = { - PORT_DSP, - DSP_RX_FIRST_LINE, - BP_LAST_LINE -}; - -// send to ETH -buf_cmd_args_t dsp_rx_send_args = { - PORT_ETH, - 0, // starts with ethernet header in line 0 - 0, // filled in from list_line register -}; - -dbsm_t dsp_rx_sm; // the state machine -#endif - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; - - -// variables for streaming mode - -static bool streaming_p = false; -static unsigned int streaming_items_per_frame = 0; -static int streaming_frame_count = 0; -#define FRAMES_PER_CMD 1000 - -bool is_streaming(void){ return streaming_p; } - - -// ---------------------------------------------------------------- - - -void -restart_streaming(void) -{ -#if 0 - // setup RX DSP regs - dsp_rx_regs->clear_state = 1; // reset - - streaming_p = true; - streaming_frame_count = FRAMES_PER_CMD; - - dsp_rx_regs->rx_command = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - streaming_items_per_frame, - 1, 1); // set "chain" bit - - // kick off the state machine - dbsm_start(&dsp_rx_sm); - - dsp_rx_regs->rx_time = 0; // enqueue first of two commands - - // make sure this one and the rest have the "now" and "chain" bits set. - dsp_rx_regs->rx_command = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - streaming_items_per_frame, - 1, 1); - - dsp_rx_regs->rx_time = 0; // enqueue second command -#endif -} - -void -start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p) -{ -#if 0 - host_mac_addr = *host; // remember who we're sending to - - /* - * Construct ethernet header and word0 and preload into two buffers - */ - u2_eth_packet_t pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.ehdr.dst = *host; - pkt.ehdr.src = *ethernet_mac_addr(); - pkt.ehdr.ethertype = U2_ETHERTYPE; - u2p_set_word0(&pkt.fixed, 0, 0); - // DSP RX will fill in timestamp - - memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt)); - memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt)); - - - if (FW_SETS_SEQNO) - fw_seqno = 0; - - streaming_items_per_frame = p->items_per_frame; - restart_streaming(); -#endif -} - - -void -stop_rx_cmd(void) -{ -#if 0 - streaming_p = false; - dsp_rx_regs->clear_state = 1; // flush cmd queue - bp_clear_buf(DSP_RX_BUF_0); - bp_clear_buf(DSP_RX_BUF_1); -#endif -} - - -static void -setup_tx() -{ - dsp_tx_regs->clear_state = 1; - - int tx_scale = 2500; - int interp = 8; // * 4 - - // setup some defaults - - dsp_tx_regs->freq = 429496730; // 10MHz - dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; - dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp; -} - - -#if 0 -#if (FW_SETS_SEQNO) -/* - * Debugging ONLY. This will be handled by the tx_protocol_engine. - * - * This is called when the DSP Rx chain has filled in a packet. - * We set and increment the seqno, then return false, indicating - * that we didn't handle the packet. A bit of a kludge - * but it should work. - */ -int -fw_sets_seqno_inspector(bsm12_t *sm, int buf_this) -{ - uint32_t *p = buffer_ram(buf_this); - uint32_t seqno = fw_seqno++; - - // KLUDGE all kinds of nasty magic numbers and embedded knowledge - uint32_t t = p[4]; - t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); - p[4] = t; - - // queue up another rx command when required - if (streaming_p && --streaming_frame_count == 0){ - streaming_frame_count = FRAMES_PER_CMD; - dsp_rx_regs->rx_time = 0; - } - - return false; // we didn't handle the packet -} -#endif -#endif - - -inline static void -buffer_irq_handler(unsigned irq) -{ - uint32_t status = buffer_pool_status->status; - - bsm12_process_status(&bsm12_sm, status); -} - -int -main(void) -{ - u2_init(); - - putstr("\nMIMO Tx\n"); - print_mac_addr(ethernet_mac_addr()->addr); - newline(); - - ethernet_register_link_changed_callback(link_changed_callback); - ethernet_init(); - - clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO); - -#if 0 - // make bit 15 of Tx gpio's be a s/w output - hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); - hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); -#endif - - output_regs->debug_mux_ctrl = 1; -#if 0 - hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); - hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); -#endif - - - // initialize double buffering state machine for ethernet -> DSP Tx - - bsm12_init(&bsm12_sm, BUF_BSM12_0, - &bsm12_recv_args, &bsm12_send0_args, &bsm12_send1_args, - eth_pkt_inspector); - - -#if 0 - // initialize double buffering state machine for DSP RX -> Ethernet - - if (FW_SETS_SEQNO){ - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - fw_sets_seqno_inspector); - } - else { - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - dbsm_nop_inspector); - } - - // tell app_common that this dbsm could be sending to the ethernet - ac_could_be_sending_to_eth = &dsp_rx_sm; -#endif - - - // program tx registers - setup_tx(); - - // kick off the state machine - bsm12_start(&bsm12_sm); - - //int which = 0; - - while(1){ - // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); - // which ^= 0x8000; - - buffer_irq_handler(0); - - int pending = pic_regs->pending; // poll for under or overrun - - if (pending & PIC_UNDERRUN_INT){ - // dbsm_handle_tx_underrun(&dsp_tx_sm); - pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt - putchar('U'); - } - - if (pending & PIC_OVERRUN_INT){ - // dbsm_handle_rx_overrun(&dsp_rx_sm); - pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt - - // FIXME Figure out how to handle this robustly. - // Any buffers that are emptying should be allowed to drain... - - if (streaming_p){ - // restart_streaming(); - // FIXME report error - } - else { - // FIXME report error - } - putchar('O'); - } - } -} diff --git a/firmware/microblaze/apps/mimo_tx_slave.c b/firmware/microblaze/apps/mimo_tx_slave.c deleted file mode 100644 index cdf9c03c2..000000000 --- a/firmware/microblaze/apps/mimo_tx_slave.c +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright 2007,2008,2009 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, see . - */ - -/* - * This is a down and dirty test program that confirms that the we can - * coherently transmit different signals to two USRP2s connected via a - * mimo cable. This code runs in the USRP2 NOT connected to the - * ethernet. The USRP connected to the ethernet runs mimo_tx. The - * host runs test_mimo_tx. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "app_common_v2.h" -#include "memcpy_wa.h" -#include "clocks.h" -#include -#include -#include - - -#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) - -#if (FW_SETS_SEQNO) -static int fw_seqno; // used when f/w is filling in sequence numbers -#endif - - -/* - * Full duplex Tx and Rx between serdes and DSP pipelines - * - * Buffer 1 is used by the cpu to send frames to the host. - * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow - * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow - */ -//#define CPU_RX_BUF 0 // eth -> cpu - -#define DSP_RX_BUF_0 2 // dsp rx -> serdes (double buffer) -#define DSP_RX_BUF_1 3 // dsp rx -> serdes -#define DSP_TX_BUF_0 4 // serdes -> dsp tx (double buffer) -#define DSP_TX_BUF_1 5 // serdes -> dsp tx - -/* - * ================================================================== - * configure DSP TX double buffering state machine (serdes -> dsp) - * ================================================================== - */ - -// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) -// DSP Tx reads word0 (flags) + timestamp followed by samples - -#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) - -// Receive from serdes -buf_cmd_args_t dsp_tx_recv_args = { - PORT_SERDES, - 0, - BP_LAST_LINE -}; - -// send to DSP Tx -buf_cmd_args_t dsp_tx_send_args = { - PORT_DSP, - DSP_TX_FIRST_LINE, // starts just past transport header - 0 // filled in from last_line register -}; - -dbsm_t dsp_tx_sm; // the state machine - -/* - * ================================================================= - * configure DSP RX double buffering state machine (dsp -> serdes) - * ================================================================= - */ - -// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0) -// DSP Rx writes timestamp followed by nlines_per_frame of samples -#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1) - -// receive from DSP -buf_cmd_args_t dsp_rx_recv_args = { - PORT_DSP, - DSP_RX_FIRST_LINE, - BP_LAST_LINE -}; - -// send to serdes -buf_cmd_args_t dsp_rx_send_args = { - PORT_SERDES, - 0, // starts with ethernet header in line 0 - 0, // filled in from list_line register -}; - -dbsm_t dsp_rx_sm; // the state machine - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; - - -// variables for streaming mode - -static bool streaming_p = false; -static unsigned int streaming_items_per_frame = 0; -static int streaming_frame_count = 0; -#define FRAMES_PER_CMD 1000 - -bool is_streaming(void){ return streaming_p; } - -// ---------------------------------------------------------------- - - -void -restart_streaming(void) -{ - // setup RX DSP regs - dsp_rx_regs->clear_state = 1; // reset - - streaming_p = true; - streaming_frame_count = FRAMES_PER_CMD; - - dsp_rx_regs->rx_command = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - streaming_items_per_frame, - 1, 1); // set "chain" bit - - // kick off the state machine - dbsm_start(&dsp_rx_sm); - - dsp_rx_regs->rx_time = 0; // enqueue first of two commands - - // make sure this one and the rest have the "now" and "chain" bits set. - dsp_rx_regs->rx_command = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - streaming_items_per_frame, - 1, 1); - - dsp_rx_regs->rx_time = 0; // enqueue second command -} - -void -start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p) -{ - host_mac_addr = *host; // remember who we're sending to - - /* - * Construct ethernet header and word0 and preload into two buffers - */ - u2_eth_packet_t pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.ehdr.dst = *host; - pkt.ehdr.src = *ethernet_mac_addr(); - pkt.ehdr.ethertype = U2_ETHERTYPE; - u2p_set_word0(&pkt.fixed, 0, 0); - // DSP RX will fill in timestamp - - memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt)); - memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt)); - - - if (FW_SETS_SEQNO) - fw_seqno = 0; - - streaming_items_per_frame = p->items_per_frame; - restart_streaming(); -} - - -void -stop_rx_cmd(void) -{ - streaming_p = false; - dsp_rx_regs->clear_state = 1; // flush cmd queue - bp_clear_buf(DSP_RX_BUF_0); - bp_clear_buf(DSP_RX_BUF_1); -} - - -static void -setup_tx() -{ - dsp_tx_regs->clear_state = 1; - bp_clear_buf(DSP_TX_BUF_0); - bp_clear_buf(DSP_TX_BUF_1); - - int tx_scale = 2500; - int interp = 8; // * 4 - - // setup some defaults - - dsp_tx_regs->freq = 429496730; // 10MHz - dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; - dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp; -} - - -#if (FW_SETS_SEQNO) -/* - * Debugging ONLY. This will be handled by the tx_protocol_engine. - * - * This is called when the DSP Rx chain has filled in a packet. - * We set and increment the seqno, then return false, indicating - * that we didn't handle the packet. A bit of a kludge - * but it should work. - */ -bool -fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false -{ - uint32_t *p = buffer_ram(buf_this); - uint32_t seqno = fw_seqno++; - - // KLUDGE all kinds of nasty magic numbers and embedded knowledge - uint32_t t = p[4]; - t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); - p[4] = t; - - // queue up another rx command when required - if (streaming_p && --streaming_frame_count == 0){ - streaming_frame_count = FRAMES_PER_CMD; - dsp_rx_regs->rx_time = 0; - } - - return false; // we didn't handle the packet -} -#endif - - -inline static void -buffer_irq_handler(unsigned irq) -{ - // hal_toggle_leds(LED_A); - - uint32_t status = buffer_pool_status->status; - - if (0 && (status & ~BPS_IDLE_ALL)){ - putstr("status = "); - puthex32_nl(status); - } - - dbsm_process_status(&dsp_tx_sm, status); - dbsm_process_status(&dsp_rx_sm, status); -} - -int -main(void) -{ - u2_init(); - - output_regs->led_src = 0x3; // h/w controls bottom two bits - clocks_enable_test_clk(true, 1); - - putstr("\nMIMO Tx Slave\n"); - - cpu_tx_buf_dest_port = PORT_SERDES; - - // ethernet_register_link_changed_callback(link_changed_callback); - // ethernet_init(); - - clocks_mimo_config(MC_WE_LOCK_TO_MIMO); - - // puts("post clocks_mimo_config"); - -#if 0 - // make bit 15 of Tx gpio's be a s/w output - hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); - hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); -#endif - -#if 0 - output_regs->debug_mux_ctrl = 1; - hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000"); - hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000"); - hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); - hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); -#endif - - - // initialize double buffering state machine for ethernet -> DSP Tx - - dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, - &dsp_tx_recv_args, &dsp_tx_send_args, - eth_pkt_inspector); - - - //output_regs->flush_icache = 1; - - // initialize double buffering state machine for DSP RX -> Ethernet - - if (FW_SETS_SEQNO){ - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - fw_sets_seqno_inspector); - } - else { - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - dbsm_nop_inspector); - } - - // puts("post dbsm_init's"); - - // tell app_common that this dbsm could be sending to the ethernet - ac_could_be_sending_to_eth = &dsp_rx_sm; - - - // program tx registers - setup_tx(); - - // puts("post setup_tx"); - - // kick off the state machine - dbsm_start(&dsp_tx_sm); - - // puts("post dbsm_start"); - - //int which = 0; - - while(1){ - // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); - // which ^= 0x8000; - - buffer_irq_handler(0); - - int pending = pic_regs->pending; // poll for under or overrun - - if (pending & PIC_UNDERRUN_INT){ - dbsm_handle_tx_underrun(&dsp_tx_sm); - pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt - putchar('U'); - } - - if (pending & PIC_OVERRUN_INT){ - dbsm_handle_rx_overrun(&dsp_rx_sm); - pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt - - // FIXME Figure out how to handle this robustly. - // Any buffers that are emptying should be allowed to drain... - - if (streaming_p){ - // restart_streaming(); - // FIXME report error - } - else { - // FIXME report error - } - putchar('O'); - } - } -} diff --git a/firmware/microblaze/apps/rcv_eth_packets.c b/firmware/microblaze/apps/rcv_eth_packets.c deleted file mode 100644 index 03fc94354..000000000 --- a/firmware/microblaze/apps/rcv_eth_packets.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "memcpy_wa.h" -#include -#include - - -// ---------------------------------------------------------------- - -static eth_mac_addr_t dst_mac_addr = - {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}; - - -// ---------------------------------------------------------------- - -#define PACKET_SIZE 1500 // bytes -#define ETH_DATA_RATE 1000000 // 1MB/s -#define ETH_PACKET_RATE (ETH_DATA_RATE/PACKET_SIZE) // 13,3333 pkts/s - -#define TIMER_RATE 100000000 // 100 MHz clock - -static int timer_delta = TIMER_RATE/ETH_PACKET_RATE; // ticks between interrupts - -static volatile bool send_packet_now = false; // timer handler sets this -static volatile bool link_is_up = false; // eth handler sets this - -int packet_number = 0; - -// ---------------------------------------------------------------- - -// debugging output on tx pins -#define LS_MASK 0xE0000 -#define LS_1000 0x80000 -#define LS_100 0x40000 -#define LS_10 0x20000 - - -/* - * Called when eth phy state changes (w/ interrupts disabled) - */ -void -link_changed_callback(int speed) -{ - int v = 0; - switch(speed){ - case 10: - v = LS_10; - link_is_up = true; - break; - - case 100: - v = LS_100; - link_is_up = true; - break; - - case 1000: - v = LS_100; - link_is_up = true; - break; - - default: - v = 0; - link_is_up = false; - break; - } - - //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */ - - putstr("\neth link changed: speed = "); - puthex16_nl(speed); -} - -void -timer_irq_handler(unsigned irq) -{ - hal_set_timeout(timer_delta); // schedule next timeout - send_packet_now = 1; -} - - -void -buffer_irq_handler(unsigned irq) -{ - // FIXME -} - -static void -init_packet(int *buf, const u2_eth_packet_t *pkt, int bufnum) -{ - int i = 0; - int mark = ((bufnum & 0xff) << 24) | 0x005A0000; - - for (i = 0; i < BP_NLINES; i++){ - buf[i] = mark | i; - mark ^= 0x00FF0000; - } - - // copy header into buffer - memcpy_wa(buf, pkt, sizeof(*pkt)); -} - -static void -init_packets(void) -{ - int i; - - u2_eth_packet_t pkt __attribute__((aligned (4))); - - pkt.ehdr.dst = dst_mac_addr; - pkt.ehdr.src = *ethernet_mac_addr(); - pkt.ehdr.ethertype = U2_ETHERTYPE; - - // fill ALL buffers for debugging - for (i = 0; i < 8; i++) - init_packet((void *)buffer_ram(i), &pkt, i); -} - -int -main(void) -{ - u2_init(); - - int prev_leds = -1; - int new_leds = 0x00; - output_regs->leds = 0x00; - - int peak_hold_count = 0; - - // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output - //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - - putstr("\nrcv_eth_packets\n"); - - init_packets(); - - // pic_register_handler(IRQ_BUFFER, buffer_irq_handler); // poll for now - - // FIXME turn off timer since I don't think MTS and MFS instructions are implemented - // pic_register_handler(IRQ_TIMER, timer_irq_handler); - // hal_set_timeout(timer_delta); - - ethernet_register_link_changed_callback(link_changed_callback); - - ethernet_init(); - - //eth_mac->speed = 4; // FIXME hardcode mac speed to 1000 - - // kick off a receive - bp_receive_to_buf(2, PORT_ETH, 1, 0, 511); - - while(1){ - // u2_eth_packet_t pkt; - - new_leds = 0; - if (link_is_up) - new_leds = 0x2; - - if ((buffer_pool_status->status & (BPS_DONE_2|BPS_ERROR_2)) != 0){ - // we've got a packet! - -#if 0 - // copy to stack buffer so we can byte address it - memcpy_wa(&pkt, (void *)buffer_ram(2), sizeof(pkt)); - - putstr("Rx: src: "); - print_mac_addr(pkt.ehdr.dst_addr); - putstr(" dst: "); - print_mac_addr(pkt.ehdr.src_addr); - putstr(" ethtype: "); - puthex16(pkt.ehdr.ethertype); - putstr(" len: "); - int len = (buffer_pool_status->last_line[2] + 1) * 4; - puthex16_nl(len); -#else - volatile int *bp = buffer_ram(2); - int i; - for (i = 0; i < 16; i++){ - puthex8(i); - putchar(':'); - puthex32_nl(bp[i]); - } -#endif - - // kick off next receive - bp_clear_buf(2); - bp_receive_to_buf(2, PORT_ETH, 1, 0, 511); - - peak_hold_count = 2048 * 10; - } - - if (peak_hold_count > 0){ - peak_hold_count--; - new_leds |= 0x1; - } - - if (new_leds != prev_leds){ - prev_leds = new_leds; - output_regs->leds = new_leds; - } - } - - hal_finish(); - return 1; -} diff --git a/firmware/microblaze/apps/read_dbids.c b/firmware/microblaze/apps/read_dbids.c deleted file mode 100644 index 24c6d9ab4..000000000 --- a/firmware/microblaze/apps/read_dbids.c +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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, see . - */ - -#include -#include -#include -#include -#include - - -int main(void) -{ - u2_init(); - - puts("\nread_dbids"); - - unsigned char dbid_tx[2]; - unsigned char dbid_rx[2]; - bool ok; - - ok = eeprom_read(I2C_ADDR_TX_A, 1, dbid_tx, 2); - if (!ok){ - puts("failed to read Tx Daugherboard EEPROM"); - } - else { - putstr("Tx Daugherboard ID: "); - puthex8(dbid_tx[1]); // MSB - puthex8(dbid_tx[0]); // LSB - newline(); - } - - ok = eeprom_read(I2C_ADDR_RX_A, 1, dbid_rx, 2); - if (!ok){ - puts("failed to read Rx Daugherboard EEPROM"); - } - else { - putstr("Rx Daugherboard ID: "); - puthex8(dbid_rx[1]); // MSB - puthex8(dbid_rx[0]); // LSB - newline(); - } - - return 0; -} diff --git a/firmware/microblaze/apps/sd_bounce.c b/firmware/microblaze/apps/sd_bounce.c deleted file mode 100644 index c1b48f170..000000000 --- a/firmware/microblaze/apps/sd_bounce.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2007,2008 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, see . - */ - -/* - * Loopback SERDES to SERDES - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "nonstdio.h" -#include "memset_wa.h" -#include -#include -#include -#include -#include - - - -// ---------------------------------------------------------------- - -#define SERDES_RX_BUF_0 0 -#define SERDES_RX_BUF_1 1 - -/* - * ================================================================ - * configure SD RX double buffering state machine - * ================================================================ - */ - -// receive from SERDES -buf_cmd_args_t sd_recv_args = { - PORT_SERDES, - 0, - BP_LAST_LINE -}; - -// send to SERDES -buf_cmd_args_t sd_send_args = { - PORT_SERDES, - 0, // starts with packet in line 0 - 0, // filled in from list_line register -}; - -dbsm_t sd_sm; // the state machine - - - - -// ---------------------------------------------------------------- - -#if 0 -static bool -check_packet(int *buf, int nlines) -{ - bool ok = true; - int i = 0; - for (i = 0; i < nlines; i++){ - int expected = ((2*i + 0) << 16) | (2*i+1); - if (buf[i] != expected){ - ok = false; - printf("buf[%d] = 0x%x expected = 0x%x\n", i, buf[i], expected); - } - } - return ok; -} - -static void -zero_buffer(int bufno) -{ - memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4); -} -#endif - - -bool -sd_rx_inspector(dbsm_t *sm, int buf_this) -{ - hal_toggle_leds(0x2); - -#if 0 - int last_line = buffer_pool_status->last_line[buf_this]; - bool ok = check_packet(buffer_ram(buf_this), last_line); - static int good = 0; - static int bad = 0; - - if (ok) - good++; - else - bad++; - - if(good+bad == 10000) { - printf("Good %d\tBad %d\n",good,bad); - good = 0; - bad = 0; - } -#endif - - return false; -} - - -inline static void -buffer_irq_handler(void) -{ - uint32_t status = buffer_pool_status->status; - dbsm_process_status(&sd_sm, status); -} - - -int -main(void) -{ - u2_init(); - - putstr("\nsd_bounce\n"); - - // Get our clock from the mimo interface - clocks_mimo_config(MC_WE_LOCK_TO_MIMO); - - dbsm_init(&sd_sm, SERDES_RX_BUF_0, - &sd_recv_args, &sd_send_args, - sd_rx_inspector); - - // kick off the state machine - dbsm_start(&sd_sm); - - while(1){ - buffer_irq_handler(); - } -} diff --git a/firmware/microblaze/apps/sd_gentest.c b/firmware/microblaze/apps/sd_gentest.c deleted file mode 100644 index 35e912615..000000000 --- a/firmware/microblaze/apps/sd_gentest.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright 2007,2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "nonstdio.h" -#include "memset_wa.h" -#include -#include -#include -#include -#include - -// ---------------------------------------------------------------- - -int packet_number = 0; -volatile bool send_packet_now = 0; - -#define SERDES_TX_BUF 0 -#define SERDES_RX_BUF 1 - - -#define NLINES_PER_PKT 380 - - -// ---------------------------------------------------------------- - -//static int timer_delta = (int)(MASTER_CLK_RATE * 100e-6); -static int timer_delta = 1000000; // .01 second - -void -timer_irq_handler(unsigned irq) -{ - hal_set_timeout(timer_delta); // schedule next timeout - send_packet_now = true; -} - - -static void -init_packet(int *buf) -{ - int i = 0; - for (i = 0; i < BP_NLINES; i++){ - buf[i] = ((2*i + 0) << 16) | (2*i+1); - } -} - -static bool -check_packet(int *buf, int nlines) -{ - bool ok = true; - int i = 0; - for (i = 0; i < nlines; i++){ - int expected = ((2*i + 0) << 16) | (2*i+1); - if (buf[i] != expected){ - ok = false; - printf("buf[%d] = 0x%x expected = 0x%x\n", i, buf[i], expected); - } - } - return ok; -} - -static void -zero_buffer(int bufno) -{ - memset_wa(buffer_ram(bufno), 0, BP_NLINES * 4); -} - -static void -init_packets(void) -{ - // init just the one we're using - init_packet(buffer_ram(SERDES_TX_BUF)); -} - -int -main(void) -{ - u2_init(); - - // We're free running and provide clock to the MIMO interface - clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO); - - - // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output - // output_regs->debug_mux_ctrl = 1; - // hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - // hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - - putstr("\nsd_gentest\n"); - - // Set up serdes (already enabled) - //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN | SERDES_LOOPEN); - //output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN); - - init_packets(); - - // pic_register_handler(IRQ_TIMER, timer_irq_handler); - - //if (hwconfig_simulation_p()) - // timer_delta = sim_timer_delta; - - // start a receive from sd - zero_buffer(SERDES_RX_BUF); - bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE); - - // fire off the first packet - bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT); - hal_set_timeout(timer_delta); - int ready_to_send = 0; - - int counter __attribute__((unused)) = 0; - int sent = 1; - int txerr = 0; - int rxerr = 0; - int rcvd = 0; - int rxcrc = 0; - int sent_acc = 0; - int txerr_acc = 0; - int rxerr_acc = 0; - int rcvd_acc = 0; - int rxcrc_acc = 0; - -#define EXPECTING_PKT() ((counter & 0x1) == 0) -#define SEND_PKT() ((counter & 0x1) != 0) - - bool got_packet = false; - - while(1){ - uint32_t status = buffer_pool_status->status; - - if (status & (BPS_DONE(SERDES_RX_BUF))){ - bp_clear_buf(SERDES_RX_BUF); - got_packet = true; - - //hal_toggle_leds(0x2); - - // check packet - int last_line = buffer_pool_status->last_line[SERDES_RX_BUF]-1; - bool ok = check_packet(buffer_ram(SERDES_RX_BUF), last_line); - - if (ok) { - rcvd++; - //putchar('r'); - } - else { - rcvd++; - rxcrc++; - //putchar('P'); - } - // start a receive from sd - zero_buffer(SERDES_RX_BUF); - bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE); - } - - if (status & (BPS_ERROR(SERDES_RX_BUF))){ - bp_clear_buf(SERDES_RX_BUF); - got_packet = true; - rcvd++; - rxerr++; - //putchar('E'); - - // start a receive from sd - zero_buffer(SERDES_RX_BUF); - bp_receive_to_buf(SERDES_RX_BUF, PORT_SERDES, 1, 0, BP_LAST_LINE); - } - - if (status & (BPS_DONE(SERDES_TX_BUF))){ - bp_clear_buf(SERDES_TX_BUF); - //putchar('t'); - bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT); - //mdelay(1); - int i; - for (i = 0; i < 50; i++){ - asm volatile ("or r0, r0, r0\n\ - or r0, r0, r0\n \ - or r0, r0, r0\n \ - or r0, r0, r0\n \ - or r0, r0, r0\n \ - or r0, r0, r0\n \ - or r0, r0, r0\n"); - } - sent ++; - ready_to_send = 1; - //hal_toggle_leds(0x1); - } - - if (status & BPS_ERROR(SERDES_TX_BUF)){ - bp_clear_buf(SERDES_TX_BUF); - sent++; - txerr++; - ready_to_send = 1; - //putchar('X'); - } - - if(sent >=1000) { - printf("Status\tSENT %d\tTXERR %d\t",sent,txerr); - printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n",rcvd, rxerr, rxcrc, sent-rcvd); - sent_acc += sent; sent = 0; - txerr_acc += txerr; txerr = 0; - rcvd_acc += rcvd; rcvd = 0; - rxerr_acc += rxerr; rxerr = 0; - rxcrc_acc += rxcrc; rxcrc = 0; - } - - if(sent_acc >=10000) { - printf("\nOverall\tSENT %d\tTXERR %d\t",sent_acc,txerr_acc); - printf("RX %d\tERR %d\tCRC %d\tMISSED %d\n\n",rcvd_acc, rxerr_acc, rxcrc_acc, sent_acc-rcvd_acc); - sent_acc = 0; - txerr_acc = 0; - rcvd_acc = 0; - rxerr_acc = 0; - rxcrc_acc = 0; - } -#if 0 - int pending = pic_regs->pending; - if (pending & PIC_TIMER_INT){ - hal_set_timeout(timer_delta); - - /* - if (EXPECTING_PKT()){ - if (!got_packet) - putchar('T'); - got_packet = false; - } - - if (SEND_PKT()){ - if (status & BPS_IDLE(SERDES_TX_BUF)) - bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT); - } - counter++; - */ - - putchar('T'); - if(ready_to_send) { - bp_send_from_buf(SERDES_TX_BUF, PORT_SERDES, 1, 0, NLINES_PER_PKT); - counter++; - ready_to_send = 0; - } - - pic_regs->pending = PIC_TIMER_INT; // clear pending interrupt - } -#endif - } - - return 0; -} diff --git a/firmware/microblaze/apps/serdes_to_dsp.c b/firmware/microblaze/apps/serdes_to_dsp.c deleted file mode 100644 index 4994e0a69..000000000 --- a/firmware/microblaze/apps/serdes_to_dsp.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2007,2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "app_common.h" -#include -#include -#include - - -/* - * This program can respond to queries from the host - * and stream rx samples. - * - * Buffer 1 is used by the cpu to send frames to the host. - * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow - * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow - */ -//#define CPU_RX_BUF 0 // eth -> cpu -//#define CPU_TX_BUF 1 // cpu -> eth - -#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer) -#define DSP_RX_BUF_1 3 // dsp rx -> eth -#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer) -#define DSP_TX_BUF_1 5 // eth -> dsp tx - -/* - * ================================================================ - * configure DSP TX double buffering state machine - * ================================================================ - */ - -// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) -// DSP Tx reads word0 (flags) + timestamp followed by samples - -#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) - -// Receive from ethernet -buf_cmd_args_t dsp_tx_recv_args = { - PORT_SERDES, - 0, - BP_LAST_LINE -}; - -// send to DSP Tx -buf_cmd_args_t dsp_tx_send_args = { - PORT_DSP, - DSP_TX_FIRST_LINE, // starts just past transport header - 0 // filled in from last_line register -}; - -dbsm_t dsp_tx_sm; // the state machine - - -// ---------------------------------------------------------------- - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; - - -void -start_rx_cmd(const eth_mac_addr_t *host, op_start_rx_t *p) -{ -} - -void -stop_rx_cmd(void) -{ -} - -static void -setup_tx() -{ - dsp_tx_regs->clear_state = 1; - bp_clear_buf(DSP_TX_BUF_0); - bp_clear_buf(DSP_TX_BUF_1); - - int tx_scale = 256; - int interp = 32; - - op_config_tx_t def_config; - memset(&def_config, 0, sizeof(def_config)); - def_config.phase_inc = 408021893; // 9.5 MHz [2**32 * fc/fsample] - def_config.scale_iq = (tx_scale << 16) | tx_scale; - def_config.interp = interp; - - // setup Tx DSP regs - config_tx_cmd(&def_config); -} - - -inline static void -buffer_irq_handler(unsigned irq) -{ - //hal_toggle_leds(0x2); - - uint32_t status = buffer_pool_status->status; - - dbsm_process_status(&dsp_tx_sm, status); - - if (status & BPS_DONE(CPU_TX_BUF)){ - bp_clear_buf(CPU_TX_BUF); - } -} - -int -main(void) -{ - u2_init(); - - // Get our clock from the mimo interface - - clocks_enable_test_clk(true,1); - clocks_mimo_config(MC_WE_LOCK_TO_MIMO); - - // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output - //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - - putstr("\nserdes_to_dsp\n"); - - ethernet_register_link_changed_callback(link_changed_callback); - ethernet_init(); - - - // initialize double buffering state machine for ethernet -> DSP Tx - - dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, - &dsp_tx_recv_args, &dsp_tx_send_args, - eth_pkt_inspector); - - // program tx registers - setup_tx(); - - // kick off the state machine - dbsm_start(&dsp_tx_sm); - - while(1){ - buffer_irq_handler(0); - - int pending = pic_regs->pending; // poll for under or overrun - - if (pending & PIC_UNDERRUN_INT){ - dbsm_handle_tx_underrun(&dsp_tx_sm); - pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt - putchar('U'); - } - } -} - diff --git a/firmware/microblaze/apps/serdes_txrx.c b/firmware/microblaze/apps/serdes_txrx.c deleted file mode 100644 index 2c47c9628..000000000 --- a/firmware/microblaze/apps/serdes_txrx.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright 2007,2008,2009 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "dbsm.h" -#include "app_common_v2.h" -#include "memcpy_wa.h" -#include "clocks.h" -#include -#include -#include - - -#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now) - -#if (FW_SETS_SEQNO) -static int fw_seqno; // used when f/w is filling in sequence numbers -#endif - - -/* - * Full duplex Tx and Rx between serdes and DSP pipelines - * - * Buffer 1 is used by the cpu to send frames to the host. - * Buffers 2 and 3 are used to double-buffer the DSP Rx to serdes flow - * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow - */ -//#define CPU_RX_BUF 0 // eth -> cpu - -#define DSP_RX_BUF_0 2 // dsp rx -> serdes (double buffer) -#define DSP_RX_BUF_1 3 // dsp rx -> serdes -#define DSP_TX_BUF_0 4 // serdes -> dsp tx (double buffer) -#define DSP_TX_BUF_1 5 // serdes -> dsp tx - -/* - * ================================================================== - * configure DSP TX double buffering state machine (serdes -> dsp) - * ================================================================== - */ - -// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp) -// DSP Tx reads word0 (flags) + timestamp followed by samples - -#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4) - -// Receive from serdes -buf_cmd_args_t dsp_tx_recv_args = { - PORT_SERDES, - 0, - BP_LAST_LINE -}; - -// send to DSP Tx -buf_cmd_args_t dsp_tx_send_args = { - PORT_DSP, - DSP_TX_FIRST_LINE, // starts just past transport header - 0 // filled in from last_line register -}; - -dbsm_t dsp_tx_sm; // the state machine - -/* - * ================================================================= - * configure DSP RX double buffering state machine (dsp -> serdes) - * ================================================================= - */ - -// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0) -// DSP Rx writes timestamp followed by nlines_per_frame of samples -#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1) - -// receive from DSP -buf_cmd_args_t dsp_rx_recv_args = { - PORT_DSP, - DSP_RX_FIRST_LINE, - BP_LAST_LINE -}; - -// send to serdes -buf_cmd_args_t dsp_rx_send_args = { - PORT_SERDES, - 0, // starts with ethernet header in line 0 - 0, // filled in from list_line register -}; - -dbsm_t dsp_rx_sm; // the state machine - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; - - -// variables for streaming mode - -static bool streaming_p = false; -static unsigned int streaming_items_per_frame = 0; -static int streaming_frame_count = 0; -#define FRAMES_PER_CMD 1000 - -bool is_streaming(void){ return streaming_p; } - -// ---------------------------------------------------------------- - - -void -restart_streaming(void) -{ - // setup RX DSP regs - dsp_rx_regs->clear_state = 1; // reset - - streaming_p = true; - streaming_frame_count = FRAMES_PER_CMD; - - dsp_rx_regs->rx_command = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - streaming_items_per_frame, - 1, 1); // set "chain" bit - - // kick off the state machine - dbsm_start(&dsp_rx_sm); - - dsp_rx_regs->rx_time = 0; // enqueue first of two commands - - // make sure this one and the rest have the "now" and "chain" bits set. - dsp_rx_regs->rx_command = - MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, - streaming_items_per_frame, - 1, 1); - - dsp_rx_regs->rx_time = 0; // enqueue second command -} - -void -start_rx_streaming_cmd(const eth_mac_addr_t *host, op_start_rx_streaming_t *p) -{ - host_mac_addr = *host; // remember who we're sending to - - /* - * Construct ethernet header and word0 and preload into two buffers - */ - u2_eth_packet_t pkt; - memset(&pkt, 0, sizeof(pkt)); - pkt.ehdr.dst = *host; - pkt.ehdr.src = *ethernet_mac_addr(); - pkt.ehdr.ethertype = U2_ETHERTYPE; - u2p_set_word0(&pkt.fixed, 0, 0); - // DSP RX will fill in timestamp - - memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt)); - memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt)); - - - if (FW_SETS_SEQNO) - fw_seqno = 0; - - streaming_items_per_frame = p->items_per_frame; - restart_streaming(); -} - - -void -stop_rx_cmd(void) -{ - streaming_p = false; - dsp_rx_regs->clear_state = 1; // flush cmd queue - bp_clear_buf(DSP_RX_BUF_0); - bp_clear_buf(DSP_RX_BUF_1); -} - - -static void -setup_tx() -{ - dsp_tx_regs->clear_state = 1; - bp_clear_buf(DSP_TX_BUF_0); - bp_clear_buf(DSP_TX_BUF_1); - - int tx_scale = 256; - int interp = 32; - - // setup some defaults - - dsp_tx_regs->freq = 0; - dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; - dsp_tx_regs->interp_rate = interp; -} - - -#if (FW_SETS_SEQNO) -/* - * Debugging ONLY. This will be handled by the tx_protocol_engine. - * - * This is called when the DSP Rx chain has filled in a packet. - * We set and increment the seqno, then return false, indicating - * that we didn't handle the packet. A bit of a kludge - * but it should work. - */ -bool -fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false -{ - uint32_t *p = buffer_ram(buf_this); - uint32_t seqno = fw_seqno++; - - // KLUDGE all kinds of nasty magic numbers and embedded knowledge - uint32_t t = p[4]; - t = (t & 0xffff00ff) | ((seqno & 0xff) << 8); - p[4] = t; - - // queue up another rx command when required - if (streaming_p && --streaming_frame_count == 0){ - streaming_frame_count = FRAMES_PER_CMD; - dsp_rx_regs->rx_time = 0; - } - - return false; // we didn't handle the packet -} -#endif - - -inline static void -buffer_irq_handler(unsigned irq) -{ - // hal_toggle_leds(LED_A); - - uint32_t status = buffer_pool_status->status; - - if (0 && (status & ~BPS_IDLE_ALL)){ - putstr("status = "); - puthex32_nl(status); - } - - dbsm_process_status(&dsp_tx_sm, status); - dbsm_process_status(&dsp_rx_sm, status); -} - -int -main(void) -{ - u2_init(); - - output_regs->led_src = 0x3; // h/w controls bottom two bits - clocks_enable_test_clk(true, 1); - - putstr("\nSERDES TxRx\n"); - - cpu_tx_buf_dest_port = PORT_SERDES; - - // ethernet_register_link_changed_callback(link_changed_callback); - // ethernet_init(); - - clocks_mimo_config(MC_WE_LOCK_TO_MIMO); - - // puts("post clocks_mimo_config"); - -#if 0 - // make bit 15 of Tx gpio's be a s/w output - hal_gpio_set_sel(GPIO_TX_BANK, 15, 's'); - hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000); -#endif - -#if 0 - output_regs->debug_mux_ctrl = 1; - hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000"); - hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000"); - hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); - hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); -#endif - - - // initialize double buffering state machine for ethernet -> DSP Tx - - dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, - &dsp_tx_recv_args, &dsp_tx_send_args, - eth_pkt_inspector); - - - //output_regs->flush_icache = 1; - - // initialize double buffering state machine for DSP RX -> Ethernet - - if (FW_SETS_SEQNO){ - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - fw_sets_seqno_inspector); - } - else { - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - dbsm_nop_inspector); - } - - // puts("post dbsm_init's"); - - // tell app_common that this dbsm could be sending to the ethernet - ac_could_be_sending_to_eth = &dsp_rx_sm; - - - // program tx registers - setup_tx(); - - // puts("post setup_tx"); - - // kick off the state machine - dbsm_start(&dsp_tx_sm); - - // puts("post dbsm_start"); - - //int which = 0; - - while(1){ - // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); - // which ^= 0x8000; - - buffer_irq_handler(0); - - int pending = pic_regs->pending; // poll for under or overrun - - if (pending & PIC_UNDERRUN_INT){ - dbsm_handle_tx_underrun(&dsp_tx_sm); - pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt - putchar('U'); - } - - if (pending & PIC_OVERRUN_INT){ - dbsm_handle_rx_overrun(&dsp_rx_sm); - pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt - - // FIXME Figure out how to handle this robustly. - // Any buffers that are emptying should be allowed to drain... - - if (streaming_p){ - // restart_streaming(); - // FIXME report error - } - else { - // FIXME report error - } - putchar('O'); - } - } -} diff --git a/firmware/microblaze/apps/set_hw_rev.c b/firmware/microblaze/apps/set_hw_rev.c deleted file mode 100644 index d4ac8ff81..000000000 --- a/firmware/microblaze/apps/set_hw_rev.c +++ /dev/null @@ -1,45 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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, see . - */ -#include -#include -#include -#include - -#define HW_REV_MAJOR 0 -#define HW_REV_MINOR 3 - -int -main(void) -{ - u2_init(); - - putstr("\nset_hw_rev\n"); - - bool ok = true; - unsigned char maj = HW_REV_MAJOR; - unsigned char min = HW_REV_MINOR; - ok = eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_MSB, &maj, 1); - ok &= eeprom_write(I2C_ADDR_MBOARD, MBOARD_REV_LSB, &min, 1); - - if (ok) - printf("OK: set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); - else - printf("FAILED to set h/w rev to %d.%d\n", HW_REV_MAJOR, HW_REV_MINOR); - - return 0; -} diff --git a/firmware/microblaze/apps/test1.c b/firmware/microblaze/apps/test1.c deleted file mode 100644 index c3cc3be56..000000000 --- a/firmware/microblaze/apps/test1.c +++ /dev/null @@ -1,282 +0,0 @@ -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include "nonstdio.h" - -// Globals -#define EMPTY 0 -#define FILLING 1 -#define FULL 2 -#define EMPTYING 3 - -#define PORT 2 // ethernet = 2, serdes = 0 -int dsp_rx_buf, dsp_tx_buf, serdes_rx_buf, serdes_tx_buf; -int dsp_rx_idle, dsp_tx_idle, serdes_rx_idle, serdes_tx_idle; - -int buffer_state[4]; - - -void double_buffering(int port); - -// -// We register this in the secondary interrupt vector. -// It's called on buffer manager interrupts -// -void -buffer_irq_handler(unsigned irq) -{ - double_buffering(PORT); -} - -int -main(void) -{ - int i; - - u2_init(); - - // Control LEDs - output_regs->leds = 0x02; - - // Turn on ADCs - output_regs->adc_ctrl = 0x0A; - - // Set up TX Chain - dsp_tx_regs->freq = 0; - dsp_tx_regs->scale_iq = (1 << 16) | 1; - dsp_tx_regs->interp_rate = 8; - - // Set up RX Chain - dsp_rx_regs->freq = 0; - dsp_rx_regs->scale_iq = (1 << 16) | 1; - dsp_rx_regs->decim_rate = 8; - - // Set up buffer control, using only 4 for now - for(i=0;i<4;i++) - buffer_state[i] = EMPTY; - - // Set up DSP RX - buffer_state[0] = FILLING; - serdes_tx_idle = 1; - bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines - - //dsp_rx_regs->run_rx = 1; // Start DSP_RX - putstr("Done DSP RX setup\n"); - - // Set up serdes RX - buffer_state[2] = FILLING; - dsp_tx_idle = 1; - bp_receive_to_buf(2, PORT, 1, 5, 504); - - while (buffer_pool_status->status == 0) // wait for completion of DSP RX - ; - - putstr("Done DSP TX setup\n"); - //dsp_tx_regs->run_tx = 1; - - // register interrupt handler - pic_register_handler(IRQ_BUFFER, buffer_irq_handler); - - while (1) - ; - - hal_finish(); - return 1; -} - -void -double_buffering(int port) { - unsigned int localstatus = buffer_pool_status->status; - - if(localstatus & BPS_DONE_0) { - bp_clear_buf(0); - if(buffer_state[0] == FILLING) { - buffer_state[0] = FULL; - if(buffer_state[1] == EMPTY) { - bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines - buffer_state[1] = FILLING; - } - else - dsp_rx_idle = 1; - if(serdes_tx_idle) { - serdes_tx_idle = 0; - bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0 - buffer_state[0] = EMPTYING; - } - } - else { // buffer was emptying - buffer_state[0] = EMPTY; - if(dsp_rx_idle) { - dsp_rx_idle = 0; - bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 0, use 500 lines - buffer_state[0] = FILLING; - } - if(buffer_state[1] == FULL) { - bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1 - buffer_state[1] = EMPTYING; - } - else - serdes_tx_idle = 1; - } - putstr("Int Proc'ed 0\n"); - } - if(localstatus & BPS_DONE_1) { - bp_clear_buf(1); - if(buffer_state[1] == FILLING) { - buffer_state[1] = FULL; - if(buffer_state[0] == EMPTY) { - bp_receive_to_buf(0, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines - buffer_state[0] = FILLING; - } - else - dsp_rx_idle = 1; - if(serdes_tx_idle) { - serdes_tx_idle = 0; - bp_send_from_buf(1, port, 1, 10, 509); // SERDES_TX from buffer 1 - buffer_state[1] = EMPTYING; - } - } - else { // buffer was emptying - buffer_state[1] = EMPTY; - if(dsp_rx_idle) { - dsp_rx_idle = 0; - bp_receive_to_buf(1, 1, 1, 10, 509); // DSP_RX to buffer 1, use 500 lines - buffer_state[1] = FILLING; - } - if(buffer_state[0] == FULL) { - bp_send_from_buf(0, port, 1, 10, 509); // SERDES_TX from buffer 0 - buffer_state[0] = EMPTYING; - } - else - serdes_tx_idle = 1; - } - putstr("Int Proc'ed 1\n"); - } - if(localstatus & BPS_DONE_2) { - bp_clear_buf(2); - if(buffer_state[2] == FILLING) { - buffer_state[2] = FULL; - if(buffer_state[3] == EMPTY) { - bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3, use 500 lines - buffer_state[3] = FILLING; - } - else - serdes_rx_idle = 1; - if(dsp_tx_idle) { - dsp_tx_idle = 0; - bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2 - buffer_state[2] = EMPTYING; - } - } - else { // buffer was emptying - buffer_state[2] = EMPTY; - if(serdes_rx_idle) { - serdes_rx_idle = 0; - bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2 - buffer_state[2] = FILLING; - } - if(buffer_state[3] == FULL) { - bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3 - buffer_state[3] = EMPTYING; - } - else - dsp_tx_idle = 1; - } - putstr("Int Proc'ed 2\n"); - } - if(localstatus & BPS_DONE_3) { - bp_clear_buf(3); - if(buffer_state[3] == FILLING) { - buffer_state[3] = FULL; - if(buffer_state[2] == EMPTY) { - bp_receive_to_buf(2, port, 1, 5, 504); // SERDES_RX to buffer 2, use 500 lines - buffer_state[2] = FILLING; - } - else - serdes_rx_idle = 1; - if(dsp_tx_idle) { - dsp_tx_idle = 0; - bp_send_from_buf(3, 1, 1, 5, 504); // DSP_TX from buffer 3 - buffer_state[3] = EMPTYING; - } - } - else { // buffer was emptying - buffer_state[3] = EMPTY; - if(serdes_rx_idle) { - serdes_rx_idle = 0; - bp_receive_to_buf(3, port, 1, 5, 504); // SERDES_RX to buffer 3 - buffer_state[3] = FILLING; - } - if(buffer_state[2] == FULL) { - bp_send_from_buf(2, 1, 1, 5, 504); // DSP_TX from buffer 2 - buffer_state[2] = EMPTYING; - } - else - dsp_tx_idle = 1; - } - putstr("Int Proc'ed 3\n"); - } -} - -// Spare Code - -#if 0 - // Set up LSDAC - int i = 0; - while(1) { - int command = (3 << 19) | (0 << 16) | (i & 0xffff); - spi_transact(SPI_TXONLY, SPI_SS_TX_DAC, command, 24, 1); // negate TX phase - i++; - } -#endif - -#if 0 - // Write to buffer 0 - int *buf = (int *)(BUFFER_BASE + BUFFER_0); - puthex_nl((int)buf); - - for(i=0;i. - */ - -#include -#include -#include -#include - -int -main(void) -{ - u2_init(); - - puts("\ntest_db_spi"); - - while(1){ - spi_transact(SPI_TXONLY, SPI_SS_RX_DB, 0xCC33, 16, SPIF_PUSH_FALL); - spi_transact(SPI_TXONLY, SPI_SS_TX_DB, 0x33CC, 16, SPIF_PUSH_FALL); - } -} diff --git a/firmware/microblaze/apps/test_i2c.c b/firmware/microblaze/apps/test_i2c.c deleted file mode 100644 index f349ead88..000000000 --- a/firmware/microblaze/apps/test_i2c.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#include -#include -#include /* FIXME */ -#include -#include -#include -#include - - - -#define ASSERT_TRUE(x) \ - do { \ - if (!(x)){ \ - printf("ASSERT_TRUE failed on line %d\n", __LINE__); \ - nerrors++; \ - } \ - } while(0) - -#define ASSERT_FALSE(x) \ - do { \ - if (x){ \ - printf("ASSERT_FALSE failed on line %d\n", __LINE__); \ - nerrors++; \ - } \ - } while(0) - - -#define BUFSIZE 128 - -int -main(void) -{ - int i; - bool ok; - int nerrors = 0; - uint8_t buf[BUFSIZE]; - int not_dev_addr = 0x35; // no device with this address on the i2c bus. - int offset; - int len; - - u2_init(); - - puts("test_i2c\n"); - - // try writing a non-existent device - buf[0] = 0xA5; - ok = i2c_write(not_dev_addr, buf, 1); - ASSERT_FALSE(ok); - - // try read from non-existent device - buf[0] = 0; - ok = i2c_read(not_dev_addr, buf, 1); - ASSERT_FALSE(ok); - - // try writing eeprom - offset = 31; - len = 8; - memset(buf, 0, sizeof(buf)); - for (i = 0; i < len; i++) - buf[i] = i; - ok = eeprom_write(I2C_ADDR_MBOARD, offset, buf, len); - ASSERT_TRUE(ok); - - // now try to read it back - offset = 31; - len = 8; - memset(buf, 0, sizeof(buf)); - ok = eeprom_read(I2C_ADDR_MBOARD, offset, buf, len); - ASSERT_TRUE(ok); - - // check result - for (i = 0; i < len; i++){ - if (buf[i] != i){ - printf("buf[%d] = %d, should be %d\n", i, buf[i], i); - nerrors++; - } - } - - if (nerrors == 0){ - output_regs->leds = 0x3; - puts("PASSED\n"); - } - else { - output_regs->leds = 0x0; - puts("FAILED\n"); - } - - hal_finish(); - return 0; -} - diff --git a/firmware/microblaze/apps/test_lsadc.c b/firmware/microblaze/apps/test_lsadc.c deleted file mode 100644 index 5fda29cd7..000000000 --- a/firmware/microblaze/apps/test_lsadc.c +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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, see . - */ - -#include -#include -#include -#include -#include - -int -main(void) -{ - u2_init(); - - puts("\ntest_lsadc"); - - uint32_t r; - - unsigned int up_counter = 0; - - while (1){ - unsigned int v; - v = up_counter; - - lsdac_write_rx(0, v << 0); - lsdac_write_rx(2, v << 1); - -#if 1 - r = lsadc_read_rx(0); - lsdac_write_rx(1, r & 0x0fff); - //puthex32_nl(r); -#endif - -#if 1 - r = lsadc_read_rx(1); - lsdac_write_rx(3, r & 0x0fff); - //puthex32_nl(r); -#endif - - up_counter++; - } -} diff --git a/firmware/microblaze/apps/test_lsdac.c b/firmware/microblaze/apps/test_lsdac.c deleted file mode 100644 index 8c1bf333b..000000000 --- a/firmware/microblaze/apps/test_lsdac.c +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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, see . - */ - -#include -#include -#include -#include - -int -main(void) -{ - u2_init(); - - puts("\ntest_lsdac"); - - unsigned int up_counter = 0; - unsigned int dn_counter = 0; - - while(1){ - unsigned int v; - v = up_counter; - lsdac_write_rx(0, v << 0); - lsdac_write_rx(1, v << 1); - lsdac_write_rx(2, v << 2); - lsdac_write_rx(3, v << 3); - - v = up_counter; - lsdac_write_tx(0, v << 0); - lsdac_write_tx(1, v << 1); - lsdac_write_tx(2, v << 2); - lsdac_write_tx(3, v << 3); - - up_counter++; - dn_counter--; - } -} diff --git a/firmware/microblaze/apps/test_phy_comm.c b/firmware/microblaze/apps/test_phy_comm.c deleted file mode 100644 index d312ca4cc..000000000 --- a/firmware/microblaze/apps/test_phy_comm.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -// check communication with ethernet PHY chip - -#include "u2_init.h" -#include "memory_map.h" -#include "hal_io.h" -#include "ethernet.h" -#include "pic.h" -#include "nonstdio.h" - - -#define DELTA_T 12500000 // .125s (10ns per tick) -//#define DELTA_T 10000 - -// debugging output on tx pins -#define LS_MASK 0xE0000 -#define LS_1000 0x80000 -#define LS_100 0x40000 -#define LS_10 0x20000 - - - -#define U2_ETHERTYPE 0xBEEF - - -static volatile int led_link_up_flag = 0; - -/* - * Called when eth phy state changes (w/ interrupts disabled) - */ -void -link_changed_callback(int speed) -{ - int v = 0; - switch(speed){ - case 10: - v = LS_10; - led_link_up_flag = 0x2; - break; - - case 100: - v = LS_100; - led_link_up_flag = 0x2; - break; - - case 1000: - v = LS_100; - led_link_up_flag = 0x2; - break; - - default: - v = 0; - led_link_up_flag = 0; - break; - } - - //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */ - - putstr("\neth link changed: speed = "); - puthex_nl(speed); -} - -void -timer_handler(unsigned irq) -{ - static int led_counter = 0; - - hal_set_timeout(DELTA_T); // schedule next timeout - output_regs->leds = (led_counter++ & 0x1) | led_link_up_flag; -} - -int -main(void) -{ - u2_init(); - - putstr("\n test_phy_comm\n"); - - pic_register_handler(IRQ_ONETIME, timer_handler); - hal_set_timeout(DELTA_T); // schedule timeout - - // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output - //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - - ethernet_register_link_changed_callback(link_changed_callback); - - output_regs->phy_ctrl = 1; /* reset the eth PHY */ - output_regs->phy_ctrl = 0; - - ethernet_init(); - - while(1) - ; - - return 0; -} diff --git a/firmware/microblaze/apps/test_ram.c b/firmware/microblaze/apps/test_ram.c deleted file mode 100644 index 77ee693f6..000000000 --- a/firmware/microblaze/apps/test_ram.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#include -#include -#include /* FIXME */ -#include -#include -#include -#include -#include - -#define ASSERT_TRUE(x) \ - do { \ - if (!(x)){ \ - printf("ASSERT_TRUE failed on line %d\n", __LINE__); \ - nerrors++; \ - } \ - } while(0) - -#define ASSERT_FALSE(x) \ - do { \ - if (x){ \ - printf("ASSERT_FALSE failed on line %d\n", __LINE__); \ - nerrors++; \ - } \ - } while(0) - - -#define BUFSIZE 128 - -int test_ram() -{ - int i,j,k; - output_regs->ram_page = 1<<10; - - extram[0] = 0xDEADBEEF; - extram[1] = 0xF00D1234; - extram[7] = 0x76543210; - - output_regs->ram_page = 2<<10; - extram[7] = 0x55555555; - extram[1] = 0xaaaaaaaa; - extram[0] = 0xeeeeeeee; - - output_regs->ram_page = 1<<10; - - i = extram[0]; - k = extram[1]; - j = extram[7]; - - if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) { - puts("RAM FAIL1!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - - output_regs->ram_page = 2<<10; - - j = extram[7]; - k = extram[1]; - i = extram[0]; - - if((i != 0xeeeeeeee)||(j!=0x55555555)||(k!=0xaaaaaaaa)) { - puts("RAM FAIL2!\n"); - puthex32_nl(i); - puthex32_nl(j); - puthex32_nl(k); - return 0; - } - return 1; -} - -int -main(void) -{ - - u2_init(); - puts("\ntest_ram\n"); - int success = test_ram(); - if(success) - puts("RAM Passed Tests\n"); - else - puts("RAM Failed\n"); - - hal_finish(); - return 0; -} - diff --git a/firmware/microblaze/apps/test_sd.c b/firmware/microblaze/apps/test_sd.c deleted file mode 100644 index 494432d7f..000000000 --- a/firmware/microblaze/apps/test_sd.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#include -#include -#include /* FIXME */ -#include -#include -#include -#include - - -#define ASSERT_TRUE(x) \ - do { \ - if (!(x)){ \ - printf("ASSERT_TRUE failed on line %d\n", __LINE__); \ - nerrors++; \ - } \ - } while(0) - -#define ASSERT_FALSE(x) \ - do { \ - if (x){ \ - printf("ASSERT_FALSE failed on line %d\n", __LINE__); \ - nerrors++; \ - } \ - } while(0) - - -#define BUFSIZE 128 - -int -main(void) -{ - int i; - unsigned char buf[512]; - - u2_init(); - - puts("\ntest_sd\n"); - - - i = sd_init(); - if(i) - puts("Successfully Init'ed Card\n"); - else - puts("FAILED INIT of Card\n"); - - i = sd_read_block(2048,buf); - if(i) { - puts("READ Command accepted\n"); - for(i=0;i<512;i++) - if((i&15) == 15) - puthex8_nl(buf[i]); - else { - puthex8(buf[i]); - putchar(' '); - } - } - else - puts("READ Command Rejected\n"); - - puts("Done"); - hal_finish(); - return 0; -} - diff --git a/firmware/microblaze/apps/timer_test.c b/firmware/microblaze/apps/timer_test.c deleted file mode 100644 index 44e80b5f1..000000000 --- a/firmware/microblaze/apps/timer_test.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#include "u2_init.h" -#include "memory_map.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include "nonstdio.h" -#include "hal_io.h" - -#define DELTA_T 500 // 5 us (10ns per tick) - - -void -timer_handler(unsigned irq) -{ - hal_set_timeout(DELTA_T); - - putstr("Tick: "); - puthex_nl(0); -} - -int -main(void) -{ - u2_init(); - - // setup timer - - putstr("Setting up timer\n"); - pic_register_handler(IRQ_ONETIME, timer_handler); - - hal_set_timeout(DELTA_T); - - while (1) - ; - - putstr("Done Testing\n"); - - hal_finish(); - return 1; -} diff --git a/firmware/microblaze/apps/tx_standalone.c b/firmware/microblaze/apps/tx_standalone.c deleted file mode 100644 index 1645fa8ba..000000000 --- a/firmware/microblaze/apps/tx_standalone.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "u2_init.h" -#include "memory_map.h" -#include "spi.h" -#include "hal_io.h" -#include "buffer_pool.h" -#include "pic.h" -#include -#include "ethernet.h" -#include "nonstdio.h" -#include "usrp2_eth_packet.h" -#include "memcpy_wa.h" -#include "dbsm.h" -#include -#include -#include - -#define _AL4 __attribute__((aligned (4))) - -#define USE_BUFFER_INTERRUPT 0 // 0 or 1 - - -static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz - -/* - * This program can respond to queries from the host - * and stream rx samples. - * - * Buffer 1 is used by the cpu to send frames to the host. - * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow - * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow - */ -//#define CPU_RX_BUF 0 // eth -> cpu -#define CPU_TX_BUF 1 // cpu -> eth - -#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer) -#define DSP_RX_BUF_1 3 // dsp rx -> eth -#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer) -#define DSP_TX_BUF_1 5 // eth -> dsp tx - - -/* - * ================================================================ - * configure DSP RX double buffering state machine - * ================================================================ - */ - - -// 4 lines of ethernet hdr + 1 line (word0) -// DSP Rx writes timestamp followed by nlines_per_frame of samples -#define DSP_RX_FIRST_LINE 5 -#define DSP_RX_SAMPLES_PER_FRAME 128 -#define DSP_RX_EXTRA_LINES 1 // writes timestamp - -// Receive from DSP Rx -buf_cmd_args_t dsp_rx_recv_args = { - PORT_DSP, - DSP_RX_FIRST_LINE, - BP_LAST_LINE -}; - -// send to ethernet -buf_cmd_args_t dsp_rx_send_args = { - PORT_ETH, - 0, // starts with ethernet header in line 0 - 0, // filled in from last_line register -}; - -dbsm_t dsp_rx_sm; // the state machine - -/* - * ================================================================ - * configure DSP TX double buffering state machine - * ================================================================ - */ - -// 4 lines of ethernet hdr + 2 lines (word0 + timestamp) -// DSP Tx reads word0 (flags) + timestamp followed by samples - -#define DSP_TX_FIRST_LINE 4 -#define DSP_TX_SAMPLES_PER_FRAME 250 // not used except w/ debugging -#define DSP_TX_EXTRA_LINES 2 // reads word0 + timestamp - -// Receive from ethernet -buf_cmd_args_t dsp_tx_recv_args = { - PORT_ETH, - 0, - BP_LAST_LINE -}; - -// send to DSP Tx -buf_cmd_args_t dsp_tx_send_args = { - PORT_DSP, - DSP_TX_FIRST_LINE, // starts just past ethernet header - 0 // filled in from last_line register -}; - -dbsm_t dsp_tx_sm; // the state machine - -/* - * send constant buffer to DSP TX - */ -static inline void -SEND_CONST_TO_DSP_TX(void) -{ - bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, - DSP_TX_FIRST_LINE, - DSP_TX_FIRST_LINE + DSP_TX_EXTRA_LINES + DSP_TX_SAMPLES_PER_FRAME - 1); -} - -// ---------------------------------------------------------------- - - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; - - -void link_changed_callback(int speed); -static volatile bool link_is_up = false; // eth handler sets this - - -void -timer_irq_handler(unsigned irq) -{ - hal_set_timeout(timer_delta); // schedule next timeout -} - -// Tx DSP underrun -void -underrun_irq_handler(unsigned irq) -{ - dsp_tx_regs->clear_state = 1; - bp_clear_buf(DSP_TX_BUF_0); - bp_clear_buf(DSP_TX_BUF_1); - dbsm_stop(&dsp_tx_sm); - - // FIXME anything else? - - putstr("\nirq: underrun\n"); -} - -// Rx DSP overrun -void -overrun_irq_handler(unsigned irq) -{ - dsp_rx_regs->clear_state = 1; - bp_clear_buf(DSP_RX_BUF_0); - bp_clear_buf(DSP_RX_BUF_1); - dbsm_stop(&dsp_rx_sm); - - // FIXME anything else? - - putstr("\nirq: overrun\n"); -} - -static void -start_tx_transfers(void) -{ - bp_clear_buf(DSP_TX_BUF_0); // FIXME, really goes in state machine - bp_clear_buf(DSP_TX_BUF_1); - - // fill everything with a constant 32k + 0j - - uint32_t const_sample = (32000 << 16) | 0; - int i; - for (i = 0; i < BP_NLINES; i++){ - buffer_ram(DSP_TX_BUF_0)[i] = const_sample; - buffer_ram(DSP_TX_BUF_1)[i] = const_sample; - } - - /* - * Construct ethernet header and word0 and preload into two buffers - */ - u2_eth_packet_t pkt; - memset(&pkt, 0, sizeof(pkt)); - //pkt.ehdr.dst = *host; - pkt.ehdr.src = *ethernet_mac_addr(); - pkt.ehdr.ethertype = U2_ETHERTYPE; - u2p_set_word0(&pkt.fixed, - U2P_TX_IMMEDIATE | U2P_TX_START_OF_BURST, 0); - u2p_set_timestamp(&pkt.fixed, T_NOW); - - memcpy_wa(buffer_ram(DSP_TX_BUF_0), &pkt, sizeof(pkt)); - memcpy_wa(buffer_ram(DSP_TX_BUF_1), &pkt, sizeof(pkt)); - - - int tx_scale = 256; - - // setup Tx DSP regs - dsp_tx_regs->clear_state = 1; // reset - dsp_tx_regs->freq = 408021893; // 9.5 MHz [2**32 * fc/fsample] - dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale; - dsp_tx_regs->interp_rate = 32; - - // kick off the state machine - // dbsm_start(&dsp_rx_sm); - - SEND_CONST_TO_DSP_TX(); // send constant buffer to DSP TX -} - - -void -buffer_irq_handler(unsigned irq) -{ - uint32_t status = buffer_pool_status->status; - - if (0){ - putstr("irq: "); - puthex32(status); - putchar('\n'); - } - - if (status & BPS_ERROR_ALL){ - // FIXME rare path, handle error conditions - } - - if (status & BPS_DONE(DSP_TX_BUF_0)){ - bp_clear_buf(DSP_TX_BUF_0); - SEND_CONST_TO_DSP_TX(); - hal_toggle_leds(0x1); - } - -} - -int -main(void) -{ - u2_init(); - - // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output - //hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - //hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); - - putstr("\ntx_only\n"); - - // Control LEDs - hal_set_leds(0x0, 0x3); - - if (USE_BUFFER_INTERRUPT) - pic_register_handler(IRQ_BUFFER, buffer_irq_handler); - - pic_register_handler(IRQ_OVERRUN, overrun_irq_handler); - pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler); - - //pic_register_handler(IRQ_TIMER, timer_irq_handler); - //hal_set_timeout(timer_delta); - - ethernet_register_link_changed_callback(link_changed_callback); - - ethernet_init(); - - // initialize double buffering state machine for DSP RX -> Ethernet - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - dbsm_nop_inspector); - - // setup receive from ETH - // bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE); - -#if 0 - if (hwconfig_simulation_p()){ - // If we're simulating, pretend that we got a start command from the host - eth_mac_addr_t host = {{ 0x00, 0x0A, 0xE4, 0x3E, 0xD2, 0xD5 }}; - start_rx_cmd(&host); - } -#endif - - start_tx_transfers(); // send constant buffers to DSP TX - - while(1){ - if (!USE_BUFFER_INTERRUPT) - buffer_irq_handler(0); - } -} - -// ---------------------------------------------------------------- - -// debugging output on tx pins -#define LS_MASK 0xE0000 -#define LS_1000 0x80000 -#define LS_100 0x40000 -#define LS_10 0x20000 - -/* - * Called when eth phy state changes (w/ interrupts disabled) - */ -void -link_changed_callback(int speed) -{ - int v = 0; - switch(speed){ - case 10: - v = LS_10; - link_is_up = true; - break; - - case 100: - v = LS_100; - link_is_up = true; - break; - - case 1000: - v = LS_100; - link_is_up = true; - break; - - default: - v = 0; - link_is_up = false; - break; - } - - //hal_gpio_set_tx(v, LS_MASK); /* set debug bits on d'board */ - - // hal_set_leds(link_is_up ? 0x2 : 0x0, 0x2); - - printf("\neth link changed: speed = %d\n", speed); -} diff --git a/firmware/microblaze/include/.gitignore b/firmware/microblaze/include/.gitignore deleted file mode 100644 index b336cc7ce..000000000 --- a/firmware/microblaze/include/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/Makefile -/Makefile.in diff --git a/firmware/microblaze/include/Makefile.am b/firmware/microblaze/include/Makefile.am deleted file mode 100644 index 6afbbcd12..000000000 --- a/firmware/microblaze/include/Makefile.am +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright 2010 Ettus Research LLC -# -# Copyright 2008 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, see . -# - -include $(top_srcdir)/Makefile.common - -SUBDIRS = net - -noinst_HEADERS = \ - usrp2_fpga_regs.h \ - usrp2_i2c_addr.h \ - usrp2_clock_bits.h \ - usrp2_types.h \ - vrt/bits.h \ - vrt/types.h diff --git a/firmware/microblaze/include/compiler.h b/firmware/microblaze/include/compiler.h deleted file mode 100644 index 4fa9b49f8..000000000 --- a/firmware/microblaze/include/compiler.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 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 . - */ -#ifndef INCLUDED_COMPILER_H -#define INCLUDED_COMPILER_H - -// FIXME gcc specific. -#define _AL4 __attribute__((aligned (4))) - - -#endif /* INCLUDED_COMPILER_H */ diff --git a/firmware/microblaze/include/net/.gitignore b/firmware/microblaze/include/net/.gitignore deleted file mode 100644 index 282522db0..000000000 --- a/firmware/microblaze/include/net/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/firmware/microblaze/include/net/Makefile.am b/firmware/microblaze/include/net/Makefile.am deleted file mode 100644 index 32b0bf9dc..000000000 --- a/firmware/microblaze/include/net/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -# -# 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 $(top_srcdir)/Makefile.common - -noinst_HEADERS = \ - eth_mac_addr.h \ - padded_eth_hdr.h \ - socket_address.h diff --git a/firmware/microblaze/include/net/eth_mac_addr.h b/firmware/microblaze/include/net/eth_mac_addr.h deleted file mode 100644 index b44fb68f7..000000000 --- a/firmware/microblaze/include/net/eth_mac_addr.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2009 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 . - */ - -#ifndef INCLUDED_ETH_MAC_ADDR_H -#define INCLUDED_ETH_MAC_ADDR_H - -#include - -// Ethernet MAC address - -typedef struct { - uint8_t addr[6]; -} eth_mac_addr_t; - -#endif /* INCLUDED_ETH_MAC_ADDR_H */ diff --git a/firmware/microblaze/include/net/padded_eth_hdr.h b/firmware/microblaze/include/net/padded_eth_hdr.h deleted file mode 100644 index df816734f..000000000 --- a/firmware/microblaze/include/net/padded_eth_hdr.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009,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 . - */ -#ifndef INCLUDED_PADDED_ETH_HDR_H -#define INCLUDED_PADDED_ETH_HDR_H - -#include -#include - -/*! - * \brief Standard 14-byte ethernet header plus two leading bytes of padding. - * - * This is what a buffer contains in line 1 when using the "slow mode" - */ -typedef struct { - uint16_t pad; - eth_mac_addr_t dst; - eth_mac_addr_t src; - uint16_t ethertype; -} _AL4 padded_eth_hdr_t; - - -#endif /* INCLUDED_PADDED_ETH_HDR_H */ diff --git a/firmware/microblaze/include/net/socket_address.h b/firmware/microblaze/include/net/socket_address.h deleted file mode 100644 index 336f30a0c..000000000 --- a/firmware/microblaze/include/net/socket_address.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- c -*- */ -/* - * 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 . - */ -#ifndef INCLUDED_SOCKET_ADDRESS_H -#define INCLUDED_SOCKET_ADDRESS_H - -#include - -// port and address are in network byte order - -typedef struct socket_address { - unsigned short port; - struct ip_addr addr; -} socket_address_t; - -static inline struct socket_address -make_socket_address(struct ip_addr addr, int port) -{ - struct socket_address r; - r.port = port; - r.addr = addr; - return r; -} - - - -#endif /* INCLUDED_SOCKET_ADDRESS_H */ diff --git a/firmware/microblaze/include/usrp2_clock_bits.h b/firmware/microblaze/include/usrp2_clock_bits.h deleted file mode 100644 index d2052e941..000000000 --- a/firmware/microblaze/include/usrp2_clock_bits.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -/* - * Copyright 2008 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 this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef INCLUDED_USRP2_CLOCK_BITS_H -#define INCLUDED_USRP2_CLOCK_BITS_H - -#define _MC_WE_LOCK 0x0001 -#define _MC_MIMO_CLK_INPUT 0x0002 // else SMA input - -/* - * Derived masks (use these): - * - * We get our input from 1 of three places: - * Our free running oscilator, our SMA connector, or from the MIMO connector - */ -#define MC_WE_DONT_LOCK 0x0000 -#define MC_WE_LOCK_TO_SMA (_MC_WE_LOCK | 0) -#define MC_WE_LOCK_TO_MIMO (_MC_WE_LOCK | _MC_MIMO_CLK_INPUT) - -/* - * Independent of the source of the clock, we may or may not drive our - * clock onto the mimo connector. Note that there are dedicated clock - * signals in each direction, so disaster doesn't occurs if we're - * unnecessarily providing clock. - */ -#define MC_PROVIDE_CLK_TO_MIMO 0x0004 - -#define MC_REF_CLK_MASK 0x0f - -#define MC_PPS_SOURCE_SMA (0x00 << 4) -#define MC_PPS_SOURCE_MIMO (0x01 << 4) - -#define MC_PPS_POLARITY_NEG (0x00 << 5) -#define MC_PPS_POLARITY_POS (0x01 << 5) - -#endif /* INCLUDED_USRP2_CLOCK_BITS_H */ diff --git a/firmware/microblaze/include/usrp2_fpga_regs.h b/firmware/microblaze/include/usrp2_fpga_regs.h deleted file mode 100644 index b0f83df60..000000000 --- a/firmware/microblaze/include/usrp2_fpga_regs.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 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, see . - */ - -#ifndef INCLUDED_USRP2_FPGA_REGS_H -#define INCLUDED_USSRP2_FPGA_REGS_H - -#include "usrp2_cdefs.h" - -__U2_BEGIN_DECLS - -// ---------------------------------------------------------------- - -#define DSP_CORE_TX_BASE 128 - -// DUC center frequency tuning word (phase increment) -#define FR_TX_FREQ_0 (0 + DSP_CORE_TX_BASE) - -// I & Q output scaling, 16.0 format ((I_SCALE << 16) | Q_SCALE) -#define FR_TX_SCALE_0 (1 + DSP_CORE_TX_BASE) - -// Tx interpolation rate (set to 1 less than desired rate) -#define FR_TX_INTERP_RATE_0 (2 + DSP_CORE_TX_BASE) - -// Write 1 (actually anything) to clear tx state -#define FR_TX_CLEAR_STATE_0 (3 + DSP_CORE_TX_BASE) - -// ---------------------------------------------------------------- - -#define DSP_CORE_RX_BASE 160 - -// DDC center frequency tuning word (phase increment) -#define FR_RX_FREQ_0 (0 + DSP_CORE_RX_BASE) - -// I & Q input scaling, 16.0 format ((I_SCALE << 16) | Q_SCALE) -#define FR_RX_SCALE_0 (1 + DSP_CORE_RX_BASE) - -// Rx decimation rate (set to 1 less than desired rate) -#define FR_RX_DECIM_RATE_0 (2 + DSP_CORE_RX_BASE) - -// The next two registers concatenated are the Rx command register. -// -// Writing FR_RX_TIME_TO_RX_0 writes the concatenated value into the -// cmd queue. Thus, if you're writing both, be sure to write -// FR_RX_QTY_0 first. -// -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Timestamp | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -#define FR_RX_TIME_TO_RX (3 + DSP_CORE_RX_BASE) - -// 23-bits 9-bits -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | number_of_lines | lines_per_frame | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -#define FR_RX_QTY_0 (4 + DSP_CORE_RX_BASE) - -// write a 1 (anything actually) to clear the overrun -#define FR_RX_CLR_OVERRUN_0 (5 + DSP_CORE_RX_BASE) - - -__U2_END_DECLS - -#endif /* INCLUDED_USRP2_FPGA_REGS_H */ diff --git a/firmware/microblaze/include/usrp2_i2c_addr.h b/firmware/microblaze/include/usrp2_i2c_addr.h deleted file mode 100644 index 46f5a7556..000000000 --- a/firmware/microblaze/include/usrp2_i2c_addr.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2007 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, see . - */ - -#ifndef INCLUDED_USRP2_I2C_ADDR_H -#define INCLUDED_USRP2_I2C_ADDR_H - -// I2C addresses - -#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx - -#define I2C_ADDR_MBOARD (I2C_DEV_EEPROM | 0x0) -#define I2C_ADDR_TX_A (I2C_DEV_EEPROM | 0x4) -#define I2C_ADDR_RX_A (I2C_DEV_EEPROM | 0x5) - - -// format of USRP2 motherboard rom -// 00: 0x00 h/w rev (LSB) -// 01: 0x00 h/w rev (MSB) -// 02: 0x00 MAC addr 0 -// 03: 0x50 MAC addr 1 -// 04: 0xC2 MAC addr 2 -// 05: 0x85 MAC addr 3 -// 06: 0x3. MAC addr 4 -// 07: 0x.. MAC addr 5 - -#define MBOARD_REV_LSB 0x00 -#define MBOARD_REV_MSB 0x01 -#define MBOARD_MAC_ADDR 0x02 -#define MBOARD_IP_ADDR 0x0C - - -// format of daughterboard EEPROM -// 00: 0xDB code for ``I'm a daughterboard'' -// 01: .. Daughterboard ID (LSB) -// 02: .. Daughterboard ID (MSB) -// 03: .. io bits 7-0 direction (bit set if it's an output from m'board) -// 04: .. io bits 15-8 direction (bit set if it's an output from m'board) -// 05: .. ADC0 DC offset correction (LSB) -// 06: .. ADC0 DC offset correction (MSB) -// 07: .. ADC1 DC offset correction (LSB) -// 08: .. ADC1 DC offset correction (MSB) -// ... -// 1f: .. negative of the sum of bytes [0x00, 0x1e] - -#define DB_EEPROM_MAGIC 0x00 -#define DB_EEPROM_MAGIC_VALUE 0xDB -#define DB_EEPROM_ID_LSB 0x01 -#define DB_EEPROM_ID_MSB 0x02 -#define DB_EEPROM_OE_LSB 0x03 -#define DB_EEPROM_OE_MSB 0x04 -#define DB_EEPROM_OFFSET_0_LSB 0x05 // offset correction for ADC or DAC 0 -#define DB_EEPROM_OFFSET_0_MSB 0x06 -#define DB_EEPROM_OFFSET_1_LSB 0x07 // offset correction for ADC or DAC 1 -#define DB_EEPROM_OFFSET_1_MSB 0x08 -#define DB_EEPROM_CHKSUM 0x1f - -#define DB_EEPROM_CLEN 0x20 // length of common portion of eeprom - -#define DB_EEPROM_CUSTOM_BASE DB_EEPROM_CLEN // first avail offset for - // daughterboard specific use - -#endif /* INCLUDED_USRP2_I2C_ADDR_H */ - diff --git a/firmware/microblaze/include/usrp2_types.h b/firmware/microblaze/include/usrp2_types.h deleted file mode 100644 index fe45936f0..000000000 --- a/firmware/microblaze/include/usrp2_types.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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, see . - */ -#ifndef INCLUDED_USRP2_TYPES_H -#define INCLUDED_USRP2_TYPES_H - -#include - -/*! - * \brief Fixed point representation of a frequency in Hertz (VITA-49 compatible) - * - * 64-bit two's complement, with the radix point 20 bits up from the bottom. - * Q44.20 format (20 bits to the right of the radix point) - * - * Values range from +/- 8.79 terahertz with a resolution of 0.95 microhertz. - */ -typedef int64_t u2_fxpt_freq_t; - -#define U2_FPF_RP 20 // location of radix point in u2_fxpt_freq_t - -// macro so we can init structs at compile time -#define U2_DOUBLE_TO_FXPT_FREQ(f) (int64_t)((f) * (1LL << U2_FPF_RP)) - -static inline u2_fxpt_freq_t -u2_double_to_fxpt_freq(double f) -{ - return U2_DOUBLE_TO_FXPT_FREQ(f); -} - -static inline int -u2_fxpt_freq_round_to_int(u2_fxpt_freq_t fx) -{ - return (int)((fx+(1<<(U2_FPF_RP-1)))>>U2_FPF_RP); -} - -static inline double -u2_fxpt_freq_to_double(u2_fxpt_freq_t fx) -{ - return ((double) fx) * 1.0/(1 << U2_FPF_RP); -} - -static inline uint32_t -u2_fxpt_freq_hi(u2_fxpt_freq_t f) -{ - return ((f >> 32) & 0xffffffff); -} - -static inline uint32_t -u2_fxpt_freq_lo(u2_fxpt_freq_t f) -{ - return (f & 0xffffffff); -} - -static inline u2_fxpt_freq_t -u2_fxpt_freq_from_hilo(uint32_t hi, uint32_t lo) -{ - return (((u2_fxpt_freq_t) hi) << 32) | lo; -} - -/*! - * \brief Fixed point representation of a gain in dB (VITA-49 compatible) - * - * 16-bit two's complement, with the radix point 7 bits up from the bottom. - * Q9.7 format (7 bits to the right of the radix point) - */ -typedef int16_t u2_fxpt_gain_t; - -#define U2_FPG_RP 7 // location of radix point in u2_fxpt_gain_t - -// macro so we can init structs at compile time -#define U2_DOUBLE_TO_FXPT_GAIN(g) (int16_t)((g) * (1 << U2_FPG_RP)) - -static inline u2_fxpt_gain_t -u2_double_to_fxpt_gain(double g) -{ - return U2_DOUBLE_TO_FXPT_GAIN(g); -} - -static inline float -u2_fxpt_gain_to_double(u2_fxpt_gain_t fx) -{ - return ((double) fx) * 1.0/(1 << U2_FPG_RP); -} - -static inline int -u2_fxpt_gain_round_to_int(u2_fxpt_gain_t fx) -{ - return (int)((fx+(1<<(U2_FPG_RP-1)))>>U2_FPG_RP); -} - -#endif /* INCLUDED_USRP2_TYPES_H */ diff --git a/firmware/microblaze/include/vrt/bits.h b/firmware/microblaze/include/vrt/bits.h deleted file mode 100644 index 54eeec7b4..000000000 --- a/firmware/microblaze/include/vrt/bits.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 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, see . - */ -#ifndef INCLUDED_VRT_BITS_H -#define INCLUDED_VRT_BITS_H - -#include - - -/* VRT Header bits */ - -#define VRTH_PT_MASK (0xf << 28) -#define VRTH_PT_IF_DATA_NO_SID (0x0 << 28) // IF-Data, no stream id -#define VRTH_PT_IF_DATA_WITH_SID (0x1 << 28) // IF-Data, w/ stream id -#define VRTH_PT_EXT_DATA_NO_SID (0x2 << 28) -#define VRTH_PT_EXT_DATA_WITH_SID (0x3 << 28) -#define VRTH_PT_IF_CONTEXT (0x4 << 28) -#define VRTH_PT_EXT_CONTEXT (0x5 << 28) - -#define VRTH_HAS_CLASSID (1 << 27) -#define VRTH_HAS_TRAILER (1 << 26) // Data pkts only -#define VRTH_START_OF_BURST (1 << 25) // Data (Tx) pkts only -#define VRTH_END_OF_BURST (1 << 24) // Data (Tx) pkts only -#define VRTH_TSM (1 << 24) // Context pkts only - -#define VRTH_TSI_MASK (0x3 << 22) -#define VRTH_TSI_NONE (0x0 << 22) -#define VRTH_TSI_UTC (0x1 << 22) -#define VRTH_TSI_GPS (0x2 << 22) -#define VRTH_TSI_OTHER (0x3 << 22) - -#define VRTH_TSF_MASK (0x3 << 20) -#define VRTH_TSF_NONE (0x0 << 20) -#define VRTH_TSF_SAMPLE_CNT (0x1 << 20) -#define VRTH_TSF_REAL_TIME_PS (0x2 << 20) -#define VRTH_TSF_FREE_RUNNING (0x3 << 20) - -#define VRTH_PKT_CNT_SHIFT 16 -#define VRTH_PKT_CNT_MASK (0xf << 16) - -#define VRTH_PKT_SIZE_MASK 0xffff - - -static inline int -vrth_pkt_cnt(uint32_t h) -{ - return (h & VRTH_PKT_CNT_MASK) >> 16; -} - -static inline int -vrth_pkt_size(uint32_t h) -{ - return h & VRTH_PKT_SIZE_MASK; -} - -/* - * Trailer bits - */ -#define TR_E (1 << 8) - -#define TR_ENABLE(x) ((x) << 20) -#define TR_STATE(x) ((x) << 8) - -// Use these with TR_ENABLE and TR_STATE -#define TR_CAL_TIME (1 << 11) -#define TR_VALID_DATA (1 << 10) -#define TR_REF_LOCK (1 << 9) -#define TR_AGC (1 << 8) -#define TR_DETECTED_SIG (1 << 7) -#define TR_SPECTRAL_INVERSION (1 << 6) -#define TR_OVER_RANGE (1 << 5) -#define TR_SAMPLE_LOSS (1 << 4) -#define TR_USER_3 (1 << 3) -#define TR_USER_2 (1 << 2) -#define TR_USER_1 (1 << 1) -#define TR_USER_0 (1 << 0) - -#endif /* INCLUDED_VRT_BITS_H */ diff --git a/firmware/microblaze/include/vrt/types.h b/firmware/microblaze/include/vrt/types.h deleted file mode 100644 index edfa4ec37..000000000 --- a/firmware/microblaze/include/vrt/types.h +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 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, see . - */ -#ifndef INCLUDED_VRT_TYPES_H -#define INCLUDED_VRT_TYPES_H - -#include - -/* macros for dealing with fixed point numbers */ -#define _FXPT_C(_type, _x, _rp) ((_type)((_x)*(1ll << _rp))) -#define _FXPT_TO_INT(_x, _one) (((_x) + ((_one)/2))/(_one)) -#define _FXPT_TO_DOUBLE(_x, _one) ((double)(_x) * (1.0/(_one))) - -/*********************************************************************** - * The VRT Altitude Type (meters) - **********************************************************************/ -typedef int32_t vrt_altitude_t; -#define VRT_ALTITUDE_RP 5 -#define VRT_ALTITUDE_C(_x) _FXPT_C(vrt_altitude_t, _x, VRT_ALTITUDE_RP) - -static inline vrt_altitude_t -double_to_vrt_altitude(double num){ - return VRT_ALTITUDE_C(num); -} - -static inline int32_t -vrt_altitude_round_to_int(vrt_altitude_t fx){ - return _FXPT_TO_INT(fx, VRT_ALTITUDE_C(1)); -} - -static inline double -vrt_altitude_to_double(vrt_altitude_t fx){ - return _FXPT_TO_DOUBLE(fx, VRT_ALTITUDE_C(1)); -} - -/*********************************************************************** - * The VRT Geolocation Angle Type (degrees) - **********************************************************************/ -typedef int32_t vrt_geo_angle_t; -#define VRT_GEO_ANGLE_RP 22 -#define VRT_GEO_ANGLE_C(_x) _FXPT_C(vrt_geo_angle_t, _x, VRT_GEO_ANGLE_RP) - -static inline vrt_geo_angle_t -double_to_vrt_geo_angle(double num){ - return VRT_GEO_ANGLE_C(num); -} - -static inline int16_t -vrt_geo_angle_round_to_int(vrt_geo_angle_t fx){ - return _FXPT_TO_INT(fx, VRT_GEO_ANGLE_C(1)); -} - -static inline double -vrt_geo_angle_to_double(vrt_geo_angle_t fx){ - return _FXPT_TO_DOUBLE(fx, VRT_GEO_ANGLE_C(1)); -} - -/*********************************************************************** - * The VRT Frequency Type (Hz) - **********************************************************************/ -typedef int64_t vrt_freq_t; -#define VRT_FREQ_RP 20 -#define VRT_FREQ_C(_x) _FXPT_C(vrt_freq_t, _x, VRT_FREQ_RP) - -static inline vrt_freq_t -double_to_vrt_freq(double num){ - return VRT_FREQ_C(num); -} - -static inline int64_t -vrt_freq_round_to_int(vrt_freq_t fx){ - return _FXPT_TO_INT(fx, VRT_FREQ_C(1)); -} - -static inline double -vrt_freq_to_double(vrt_freq_t fx){ - return _FXPT_TO_DOUBLE(fx, VRT_FREQ_C(1)); -} - -/*********************************************************************** - * The VRT Gain Type (dB) - **********************************************************************/ -typedef int16_t vrt_gain_t; -#define VRT_GAIN_RP 7 -#define VRT_GAIN_C(_x) _FXPT_C(vrt_gain_t, _x, VRT_GAIN_RP) - -static inline vrt_gain_t -double_to_vrt_gain(double num){ - return VRT_GAIN_C(num); -} - -static inline int16_t -vrt_gain_round_to_int(vrt_gain_t fx){ - return _FXPT_TO_INT(fx, VRT_GAIN_C(1)); -} - -static inline double -vrt_gain_to_double(vrt_gain_t fx){ - return _FXPT_TO_DOUBLE(fx, VRT_GAIN_C(1)); -} - -/*********************************************************************** - * The VRT Temperature Type (Celcius) - **********************************************************************/ -typedef int16_t vrt_temp_t; -#define VRT_TEMP_RP 6 -#define VRT_TEMP_C(_x) _FXPT_C(vrt_temp_t, _x, VRT_TEMP_RP) - -static inline vrt_temp_t -double_to_vrt_temp(double num){ - return VRT_TEMP_C(num); -} - -static inline int16_t -vrt_temp_round_to_int(vrt_temp_t fx){ - return _FXPT_TO_INT(fx, VRT_TEMP_C(1)); -} - -static inline double -vrt_temp_to_double(vrt_temp_t fx){ - return _FXPT_TO_DOUBLE(fx, VRT_TEMP_C(1)); -} - -#endif /* INCLUDED_VRT_TYPES_H */ diff --git a/firmware/microblaze/lib/.gitignore b/firmware/microblaze/lib/.gitignore deleted file mode 100644 index 5d838bf6c..000000000 --- a/firmware/microblaze/lib/.gitignore +++ /dev/null @@ -1,40 +0,0 @@ -*~ -/*-stamp -/*.a -/*.bin -/*.dump -/*.log -/*.rom -/.deps -/Makefile -/Makefile.in -/aclocal.m4 -/autom4te.cache -/blink_leds -/blink_leds2 -/build -/compile -/config.h -/config.h.in -/config.log -/config.status -/configure -/depcomp -/eth_test -/gen_eth_packets -/ibs_rx_test -/ibs_tx_test -/install-sh -/libtool -/ltmain.sh -/missing -/py-compile -/rcv_eth_packets -/run_tests.sh -/stamp-h1 -/test1 -/test_phy_comm -/timer_test -/buf_ram_test -/buf_ram_zero -/hello diff --git a/firmware/microblaze/lib/Makefile.am b/firmware/microblaze/lib/Makefile.am deleted file mode 100644 index b51d74463..000000000 --- a/firmware/microblaze/lib/Makefile.am +++ /dev/null @@ -1,87 +0,0 @@ -# -# Copyright 2010 Ettus Research LLC -# -# Copyright 2007 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, see . -# - -include $(top_srcdir)/Makefile.common - -noinst_LIBRARIES = \ - libu2fw.a - -libu2fw_a_SOURCES = \ - abort.c \ - ad9510.c \ - bsm12.c \ - buffer_pool.c \ - clocks.c \ - dbsm.c \ - eeprom.c \ - ethernet.c \ - eth_mac.c \ - _exit.c \ - exit.c \ - hal_io.c \ - hal_uart.c \ - i2c.c \ - mdelay.c \ - memcpy_wa.c \ - memset_wa.c \ - nonstdio.c \ - pic.c \ - print_mac_addr.c \ - print_rmon_regs.c \ - print_buffer.c \ - printf.c \ - sd.c \ - spi.c \ - u2_init.c \ - net_common.c \ - arp_cache.c \ - banal.c - -noinst_HEADERS = \ - ad9510.h \ - bsm12.h \ - buffer_pool.h \ - clocks.h \ - dbsm.h \ - eth_mac.h \ - eth_mac_regs.h \ - eth_phy.h \ - ethernet.h \ - hal_io.h \ - hal_uart.h \ - i2c.h \ - mdelay.h \ - memcpy_wa.h \ - memory_map.h \ - memset_wa.h \ - nonstdio.h \ - pic.h \ - print_rmon_regs.h \ - sd.h \ - spi.h \ - stdint.h \ - stdio.h \ - u2_init.h \ - usrp2_bytesex.h \ - wb16550.h \ - net_common.h \ - if_arp.h \ - arp_cache.h \ - banal.h \ - ethertype.h diff --git a/firmware/microblaze/lib/clocks.c b/firmware/microblaze/lib/clocks.c deleted file mode 100644 index ccc4a7cc7..000000000 --- a/firmware/microblaze/lib/clocks.c +++ /dev/null @@ -1,239 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include - -#include "memory_map.h" -#include "ad9510.h" -#include "spi.h" -#include "u2_init.h" -#include "nonstdio.h" - -void -clocks_init(void) -{ - // Set up basic clocking functions in AD9510 - ad9510_write_reg(0x45, 0x00); // CLK2 drives distribution - - clocks_enable_fpga_clk(true, 1); - - spi_wait(); - - // Set up PLL for 10 MHz reference - // Reg 4, A counter, Don't Care - ad9510_write_reg(0x05, 0x00); // Reg 5, B counter MSBs, 0 - ad9510_write_reg(0x06, 0x05); // Reg 6, B counter LSBs, 5 - // Reg 7, Loss of reference detect, doesn't work yet, 0 - ad9510_write_reg(0x5A, 0x01); // Update Regs - - // Primary clock configuration - clocks_mimo_config(MC_WE_DONT_LOCK); - - // Set up other clocks - //clocks_enable_test_clk(false, 0); - //clocks_enable_tx_dboard(false, 0); - //clocks_enable_rx_dboard(false, 0); - clocks_enable_eth_phyclk(false, 0); - - // Enable clock to ADCs and DACs - //clocks_enable_dac_clk(true, 1); - //clocks_enable_adc_clk(true, 1); -} - - -void -clocks_mimo_config(int flags) -{ - if (flags & _MC_WE_LOCK){ - // Reg 8, Charge pump on, dig lock det, positive PFD, 47 - ad9510_write_reg(0x08, 0x47); - } - else { - // Reg 8, Charge pump off, dig lock det, positive PFD - ad9510_write_reg(0x08, 0x00); - } - - // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA - ad9510_write_reg(0x09, 0x00); - // Reg A, Prescaler of 2, everything normal 04 - ad9510_write_reg(0x0A, 0x04); - // Reg B, R Div MSBs, 0 - ad9510_write_reg(0x0B, 0x00); - // Reg C, R Div LSBs, 1 - ad9510_write_reg(0x0C, 0x01); - // Reg D, Antibacklash, Digital lock det, 0 - - ad9510_write_reg(0x5A, 0x01); // Update Regs - - spi_wait(); - - // Allow for clock switchover - - if (flags & _MC_WE_LOCK){ // WE LOCK - if (flags & _MC_MIMO_CLK_INPUT) { - // Turn on ref output and choose the MIMO connector - output_regs->clk_ctrl = 0x15; - } - else { - // turn on ref output and choose the SMA - output_regs->clk_ctrl = 0x1C; - } - } - else { // WE DONT LOCK - // Disable both ext clk inputs - output_regs->clk_ctrl = 0x10; - } - - // Do we drive a clock onto the MIMO connector? - if (flags & MC_PROVIDE_CLK_TO_MIMO) - clocks_enable_clkexp_out(true,10); - else - clocks_enable_clkexp_out(false,0); -} - -bool -clocks_lock_detect() -{ - if(pic_regs->pending & PIC_CLKSTATUS) - return true; - return false; -} - -int inline -clocks_gen_div(int divisor) -{ - int L,H; - L = (divisor>>1)-1; - H = divisor-L-2; - return (L<<4)|H; -} - -#define CLOCK_OUT_EN 0x08 -#define CLOCK_OUT_DIS_CMOS 0x01 -#define CLOCK_OUT_DIS_PECL 0x02 -#define CLOCK_DIV_DIS 0x80 -#define CLOCK_DIV_EN 0x00 - -#define CLOCK_MODE_PECL 1 -#define CLOCK_MODE_LVDS 2 -#define CLOCK_MODE_CMOS 3 - -void -clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mode) -{ - int enable_word, div_word, div_en_word; - - switch(mode) { - case CLOCK_MODE_PECL : - enable_word = enable ? 0x08 : 0x0A; - break; - case CLOCK_MODE_LVDS : - enable_word = enable ? 0x02 : 0x03; - break; - case CLOCK_MODE_CMOS : - enable_word = enable ? 0x08 : 0x09; - break; - } - if(enable && (divisor>1)) { - div_word = clocks_gen_div(divisor); - div_en_word = CLOCK_DIV_EN; - } - else { - div_word = 0; - div_en_word = CLOCK_DIV_DIS; - } - - ad9510_write_reg(reg_en,enable_word); // Output en/dis - ad9510_write_reg(reg_div,div_word); // Set divisor - ad9510_write_reg(reg_div+1,div_en_word); // Enable or Bypass Divider - ad9510_write_reg(0x5A, 0x01); // Update Regs -} - -// Clock 0 -/*void -clocks_enable_test_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL); -}*/ - -// Clock 1 -void -clocks_enable_fpga_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL); -} - -// Clock 2 on Rev 3, Clock 5 on Rev 4 -void -clocks_enable_clkexp_out(bool enable, int divisor) -{ - if(u2_hw_rev_major == 3) - clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); - else if(u2_hw_rev_major == 4) { - ad9510_write_reg(0x34,0x00); // Turn on fine delay - ad9510_write_reg(0x35,0x00); // Set Full Scale to nearly 10ns - ad9510_write_reg(0x36,0x1c); // Set fine delay. 0x20 is midscale - clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); - - } - else - putstr("ERR: Invalid Rev\n"); -} - -// Clock 5 on Rev 3, none (was 2) on Rev 4 -void -clocks_enable_eth_phyclk(bool enable, int divisor) -{ - if(u2_hw_rev_major == 3) - clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); - else if(u2_hw_rev_major == 4) - clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); - else - putstr("ERR: Invalid Rev\n"); -} - -// Clock 3 -/*void -clocks_enable_dac_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL); -}*/ - -// Clock 4 -/*void -clocks_enable_adc_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS); -}*/ - -// Clock 6 -/*void -clocks_enable_tx_dboard(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS); -}*/ - -// Clock 7 -/*void -clocks_enable_rx_dboard(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS); -}*/ diff --git a/firmware/microblaze/lib/memory_map.h b/firmware/microblaze/lib/memory_map.h deleted file mode 100644 index cdf3dd338..000000000 --- a/firmware/microblaze/lib/memory_map.h +++ /dev/null @@ -1,792 +0,0 @@ -/* -*- c -*- */ -/* - * Copyright 2007,2008,2009 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, see . - */ - -/* Overall Memory Map - * 0000-7FFF 32K RAM space (16K on 1500, 24K on 2000, 32K on DSP) - * 8000-BFFF 16K Buffer Pool - * C000-FFFF 16K Peripherals - */ - - -#ifndef INCLUDED_MEMORY_MAP_H -#define INCLUDED_MEMORY_MAP_H - -#include - - -#define MASTER_CLK_RATE 100000000 // 100 MHz - - -//////////////////////////////////////////////////////////////// -// -// Memory map for embedded wishbone bus -// -//////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////// -// Main RAM, Slave 0 - -#define RAM_BASE 0x0000 - -//////////////////////////////////////////////////////////////// -// Buffer Pool RAM, Slave 1 -// -// The buffers themselves are located in Slave 1, Buffer Pool RAM. -// The status registers are in Slave 5, Buffer Pool Status. -// The control register is in Slave 7, Settings Bus. - -#define BUFFER_POOL_RAM_BASE 0x8000 - -#define NBUFFERS 8 -#define BP_NLINES 0x0200 // number of 32-bit lines in a buffer -#define BP_LAST_LINE (BP_NLINES - 1) // last line in a buffer - -#define buffer_pool_ram \ - ((uint32_t *) BUFFER_POOL_RAM_BASE) - -#define buffer_ram(n) (&buffer_pool_ram[(n) * BP_NLINES]) - - -///////////////////////////////////////////////////// -// SPI Core, Slave 2. See core docs for more info -#define SPI_BASE 0xC000 // Base address (16-bit) - -typedef struct { - volatile uint32_t txrx0; - volatile uint32_t txrx1; - volatile uint32_t txrx2; - volatile uint32_t txrx3; - volatile uint32_t ctrl; - volatile uint32_t div; - volatile uint32_t ss; -} spi_regs_t; - -#define spi_regs ((spi_regs_t *) SPI_BASE) - - -// Masks for controlling different peripherals -#define SPI_SS_AD9510 1 -#define SPI_SS_AD9777 2 -#define SPI_SS_RX_DAC 4 -#define SPI_SS_RX_ADC 8 -#define SPI_SS_RX_DB 16 -#define SPI_SS_TX_DAC 32 -#define SPI_SS_TX_ADC 64 -#define SPI_SS_TX_DB 128 - -// Masks for different parts of CTRL reg -#define SPI_CTRL_ASS (1<<13) -#define SPI_CTRL_IE (1<<12) -#define SPI_CTRL_LSB (1<<11) -#define SPI_CTRL_TXNEG (1<<10) -#define SPI_CTRL_RXNEG (1<< 9) -#define SPI_CTRL_GO_BSY (1<< 8) -#define SPI_CTRL_CHAR_LEN_MASK 0x7F - -//////////////////////////////////////////////// -// I2C, Slave 3 -// See Wishbone I2C-Master Core Specification. - -#define I2C_BASE 0xC400 - -typedef struct { - volatile uint32_t prescaler_lo; // r/w - volatile uint32_t prescaler_hi; // r/w - volatile uint32_t ctrl; // r/w - volatile uint32_t data; // wr = transmit reg; rd = receive reg - volatile uint32_t cmd_status; // wr = command reg; rd = status reg -} i2c_regs_t; - -#define i2c_regs ((i2c_regs_t *) I2C_BASE) - -#define I2C_CTRL_EN (1 << 7) // core enable -#define I2C_CTRL_IE (1 << 6) // interrupt enable - -// -// STA, STO, RD, WR, and IACK bits are cleared automatically -// -#define I2C_CMD_START (1 << 7) // generate (repeated) start condition -#define I2C_CMD_STOP (1 << 6) // generate stop condition -#define I2C_CMD_RD (1 << 5) // read from slave -#define I2C_CMD_WR (1 << 4) // write to slave -#define I2C_CMD_NACK (1 << 3) // when a rcvr, send ACK (ACK=0) or NACK (ACK=1) -#define I2C_CMD_RSVD_2 (1 << 2) // reserved -#define I2C_CMD_RSVD_1 (1 << 1) // reserved -#define I2C_CMD_IACK (1 << 0) // set to clear pending interrupt - -#define I2C_ST_RXACK (1 << 7) // Received acknowledgement from slave (1 = NAK, 0 = ACK) -#define I2C_ST_BUSY (1 << 6) // 1 after START signal detected; 0 after STOP signal detected -#define I2C_ST_AL (1 << 5) // Arbitration lost. 1 when core lost arbitration -#define I2C_ST_RSVD_4 (1 << 4) // reserved -#define I2C_ST_RSVD_3 (1 << 3) // reserved -#define I2C_ST_RSVD_2 (1 << 2) // reserved -#define I2C_ST_TIP (1 << 1) // Transfer-in-progress -#define I2C_ST_IP (1 << 0) // Interrupt pending - - -//////////////////////////////////////////////// -// GPIO, Slave 4 -// -// These go to the daughterboard i/o pins - -#define GPIO_BASE 0xC800 - -typedef struct { - volatile uint32_t io; // tx data in high 16, rx in low 16 - volatile uint32_t ddr; // 32 bits, 1 means output. tx in high 16, rx in low 16 - volatile uint32_t tx_sel; // 16 2-bit fields select which source goes to TX DB - volatile uint32_t rx_sel; // 16 2-bit fields select which source goes to RX DB -} gpio_regs_t; - -// each 2-bit sel field is layed out this way -#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg -#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic -#define GPIO_SEL_DEBUG_0 2 // if pin is an output, debug lines from FPGA fabric -#define GPIO_SEL_DEBUG_1 3 // if pin is an output, debug lines from FPGA fabric - -#define gpio_base ((gpio_regs_t *) GPIO_BASE) - -/////////////////////////////////////////////////// -// Buffer Pool Status, Slave 5 -// -// The buffers themselves are located in Slave 1, Buffer Pool RAM. -// The status registers are in Slave 5, Buffer Pool Status. -// The control register is in Slave 7, Settings Bus. - -#define BUFFER_POOL_STATUS_BASE 0xCC00 - -typedef struct { - volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer - volatile uint32_t status; // error and done flags - volatile uint32_t hw_config; // see below - volatile uint32_t dummy[3]; - volatile uint32_t irqs; - volatile uint32_t pri_enc_bp_status; - volatile uint32_t cycle_count; -} buffer_pool_status_t; - -#define buffer_pool_status ((buffer_pool_status_t *) BUFFER_POOL_STATUS_BASE) - -/* - * Buffer n's xfer is done. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_DONE(n) (0x00000001 << (n)) -#define BPS_DONE_0 BPS_DONE(0) -#define BPS_DONE_1 BPS_DONE(1) -#define BPS_DONE_2 BPS_DONE(2) -#define BPS_DONE_3 BPS_DONE(3) -#define BPS_DONE_4 BPS_DONE(4) -#define BPS_DONE_5 BPS_DONE(5) -#define BPS_DONE_6 BPS_DONE(6) -#define BPS_DONE_7 BPS_DONE(7) - -/* - * Buffer n's xfer had an error. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_ERROR(n) (0x00000100 << (n)) -#define BPS_ERROR_0 BPS_ERROR(0) -#define BPS_ERROR_1 BPS_ERROR(1) -#define BPS_ERROR_2 BPS_ERROR(2) -#define BPS_ERROR_3 BPS_ERROR(3) -#define BPS_ERROR_4 BPS_ERROR(4) -#define BPS_ERROR_5 BPS_ERROR(5) -#define BPS_ERROR_6 BPS_ERROR(6) -#define BPS_ERROR_7 BPS_ERROR(7) - -/* - * Buffer n is idle. A buffer is idle if it's not - * DONE, ERROR, or processing a transaction. If it's - * IDLE, it's safe to start a new transaction. - * - * Clear this bit by starting a xfer with - * bp_send_from_buf or bp_receive_to_buf. - */ -#define BPS_IDLE(n) (0x00010000 << (n)) -#define BPS_IDLE_0 BPS_IDLE(0) -#define BPS_IDLE_1 BPS_IDLE(1) -#define BPS_IDLE_2 BPS_IDLE(2) -#define BPS_IDLE_3 BPS_IDLE(3) -#define BPS_IDLE_4 BPS_IDLE(4) -#define BPS_IDLE_5 BPS_IDLE(5) -#define BPS_IDLE_6 BPS_IDLE(6) -#define BPS_IDLE_7 BPS_IDLE(7) - -/* - * Buffer n has a "slow path" packet in it. - * This bit is orthogonal to the bits above and indicates that - * the FPGA ethernet rx protocol engine has identified this packet - * as one requiring firmware intervention. - */ -#define BPS_SLOWPATH(n) (0x01000000 << (n)) -#define BPS_SLOWPATH_0 BPS_SLOWPATH(0) -#define BPS_SLOWPATH_1 BPS_SLOWPATH(1) -#define BPS_SLOWPATH_2 BPS_SLOWPATH(2) -#define BPS_SLOWPATH_3 BPS_SLOWPATH(3) -#define BPS_SLOWPATH_4 BPS_SLOWPATH(4) -#define BPS_SLOWPATH_5 BPS_SLOWPATH(5) -#define BPS_SLOWPATH_6 BPS_SLOWPATH(6) -#define BPS_SLOWPATH_7 BPS_SLOWPATH(7) - - -#define BPS_DONE_ALL 0x000000ff // mask of all dones -#define BPS_ERROR_ALL 0x0000ff00 // mask of all errors -#define BPS_IDLE_ALL 0x00ff0000 // mask of all idles -#define BPS_SLOWPATH_ALL 0xff000000 // mask of all slowpaths - -// The hw_config register - -#define HWC_SIMULATION 0x80000000 -#define HWC_WB_CLK_DIV_MASK 0x0000000f - -/*! - * \brief return non-zero if we're running under the simulator - */ -inline static int -hwconfig_simulation_p(void) -{ - return buffer_pool_status->hw_config & HWC_SIMULATION; -} - -/*! - * \brief Return Wishbone Clock divisor. - * The processor runs at the Wishbone Clock rate which is MASTER_CLK_RATE / divisor. - */ -inline static int -hwconfig_wishbone_divisor(void) -{ - return buffer_pool_status->hw_config & HWC_WB_CLK_DIV_MASK; -} - -/////////////////////////////////////////////////// -// Ethernet Core, Slave 6 - -#define ETH_BASE 0xD000 - -#include "eth_mac_regs.h" - -#define eth_mac ((eth_mac_regs_t *) ETH_BASE) - -//////////////////////////////////////////////////// -// Settings Bus, Slave #7, Not Byte Addressable! -// -// Output-only from processor point-of-view. -// 1KB of address space (== 256 32-bit write-only regs) - - -#define MISC_OUTPUT_BASE 0xD400 -#define TX_PROTOCOL_ENGINE_BASE 0xD480 -#define RX_PROTOCOL_ENGINE_BASE 0xD4C0 -#define BUFFER_POOL_CTRL_BASE 0xD500 -#define LAST_SETTING_REG 0xD7FC // last valid setting register - -#define SR_MISC 0 -#define SR_TX_PROT_ENG 32 -#define SR_RX_PROT_ENG 48 -#define SR_BUFFER_POOL_CTRL 64 -#define SR_UDP_SM 96 -#define SR_TX_DSP 208 -#define SR_TX_CTRL 224 -#define SR_RX_DSP 160 -#define SR_RX_CTRL 176 -#define SR_TIME64 192 -#define SR_SIMTIMER 198 -#define SR_LAST 255 - -#define _SR_ADDR(sr) (MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t)) - -// --- buffer pool control regs --- - -typedef struct { - volatile uint32_t ctrl; -} buffer_pool_ctrl_t; - -// buffer pool ports - -#define PORT_SERDES 0 // serial/deserializer -#define PORT_DSP 1 // DSP tx or rx pipeline -#define PORT_ETH 2 // ethernet tx or rx -#define PORT_RAM 3 // RAM tx or rx - -// the buffer pool ctrl register fields - -#define BPC_BUFFER(n) (((n) & 0xf) << 28) -#define BPC_BUFFER_MASK BPC_BUFFER(~0) -#define BPC_BUFFER_0 BPC_BUFFER(0) -#define BPC_BUFFER_1 BPC_BUFFER(1) -#define BPC_BUFFER_2 BPC_BUFFER(2) -#define BPC_BUFFER_3 BPC_BUFFER(3) -#define BPC_BUFFER_4 BPC_BUFFER(4) -#define BPC_BUFFER_5 BPC_BUFFER(5) -#define BPC_BUFFER_6 BPC_BUFFER(6) -#define BPC_BUFFER_7 BPC_BUFFER(7) -#define BPC_BUFFER_NIL BPC_BUFFER(0x8) // disable - -#define BPC_PORT(n) (((n) & 0x7) << 25) -#define BPC_PORT_MASK BPC_PORT(~0) -#define BPC_PORT_SERDES BPC_PORT(PORT_SERDES) -#define BPC_PORT_DSP BPC_PORT(PORT_DSP) -#define BPC_PORT_ETH BPC_PORT(PORT_ETH) -#define BPC_PORT_RAM BPC_PORT(PORT_RAM) -#define BPC_PORT_NIL BPC_PORT(0x4) // disable - -#define BPC_CLR (1 << 24) // mutually excl commands -#define BPC_READ (1 << 23) -#define BPC_WRITE (1 << 22) - -#define BPC_STEP(step) (((step) & 0xf) << 18) -#define BPC_STEP_MASK BPC_STEP(~0) -#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9) -#define BPC_LAST_LINE_MASK BPC_LAST_LINE(~0) -#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0) -#define BPC_FIRST_LINE_MASK BPC_FIRST_LINE(~0) - -#define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE) - -// --- misc outputs --- - -typedef struct { - volatile uint32_t clk_ctrl; - volatile uint32_t serdes_ctrl; - volatile uint32_t adc_ctrl; - volatile uint32_t leds; - volatile uint32_t phy_ctrl; // LSB is reset line to eth phy - volatile uint32_t debug_mux_ctrl; - volatile uint32_t ram_page; // FIXME should go somewhere else... - volatile uint32_t flush_icache; // Flush the icache - volatile uint32_t led_src; // HW or SW control for LEDs -} output_regs_t; - -#define SERDES_ENABLE 8 -#define SERDES_PRBSEN 4 -#define SERDES_LOOPEN 2 -#define SERDES_RXEN 1 - -#define ADC_CTRL_ON 0x0F -#define ADC_CTRL_OFF 0x00 - -// crazy order that matches the labels on the case - -#define LED_A (1 << 4) -#define LED_B (1 << 1) -#define LED_C (1 << 3) -#define LED_D (1 << 0) -#define LED_E (1 << 2) -// LED_F // controlled by CPLD -#define LED_RJ45 (1 << 5) - -#define output_regs ((output_regs_t *) MISC_OUTPUT_BASE) - -// --- udp tx regs --- - -typedef struct { - // Bits 19:16 are control info; bits 15:0 are data (see below) - // First two words are unused. - volatile uint32_t _nope[2]; - //--- ethernet header - 14 bytes--- - volatile struct{ - uint32_t mac_dst_0_1; //word 2 - uint32_t mac_dst_2_3; - uint32_t mac_dst_4_5; - uint32_t mac_src_0_1; - uint32_t mac_src_2_3; - uint32_t mac_src_4_5; - uint32_t ether_type; //word 8 - } eth_hdr; - //--- ip header - 20 bytes --- - volatile struct{ - uint32_t ver_ihl_tos; //word 9 - uint32_t total_length; - uint32_t identification; - uint32_t flags_frag_off; - uint32_t ttl_proto; - uint32_t checksum; - uint32_t src_addr_high; - uint32_t src_addr_low; - uint32_t dst_addr_high; - uint32_t dst_addr_low; //word 18 - } ip_hdr; - //--- udp header - 8 bytes --- - volatile struct{ - uint32_t src_port; //word 19 - uint32_t dst_port; - uint32_t length; - uint32_t checksum; //word 22 - } udp_hdr; - volatile uint32_t _pad[32-23]; -} sr_udp_sm_t; - -// control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) - -// This is the last word of the header -#define UDP_SM_LAST_WORD (1 << 19) - -// Insert IP header checksum here. Data is the xor of 16'hFFFF and -// the values written into regs 9-13 and 15-18. -#define UDP_SM_INS_IP_HDR_CHKSUM (1 << 18) - -// Insert IP Length here (data ignored) -#define UDP_SM_INS_IP_LEN (1 << 17) - -// Insert UDP Length here (data ignore) -#define UDP_SM_INS_UDP_LEN (1 << 16) - -#define sr_udp_sm ((sr_udp_sm_t *) _SR_ADDR(SR_UDP_SM)) - -// --- dsp tx regs --- - -#define MIN_CIC_INTERP 1 -#define MAX_CIC_INTERP 128 - -typedef struct { - volatile uint32_t num_chan; - volatile uint32_t clear_state; // clears out state machine, fifos, -} sr_tx_ctrl_t; - -#define sr_tx_ctrl ((sr_tx_ctrl_t *) _SR_ADDR(SR_TX_CTRL)) - -typedef struct { - volatile int32_t freq; - volatile uint32_t scale_iq; // {scale_i,scale_q} - volatile uint32_t interp_rate; - volatile uint32_t _padding0; // padding for the tx_mux - // NOT freq, scale, interp - /*! - * \brief output mux configuration. - * - *
-   *     3                   2                   1                       
-   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   *  +-------------------------------+-------+-------+-------+-------+
-   *  |                                               | DAC1  |  DAC0 |
-   *  +-------------------------------+-------+-------+-------+-------+
-   * 
-   *  There are N DUCs (1 now) with complex inputs and outputs.
-   *  There are two DACs.
-   * 
-   *  Each 4-bit DACx field specifies the source for the DAC
-   *  Each subfield is coded like this: 
-   * 
-   *     3 2 1 0
-   *    +-------+
-   *    |   N   |
-   *    +-------+
-   * 
-   *  N specifies which DUC output is connected to this DAC.
-   * 
-   *   N   which interp output
-   *  ---  -------------------
-   *   0   DUC 0 I
-   *   1   DUC 0 Q
-   *   2   DUC 1 I
-   *   3   DUC 1 Q
-   *   F   All Zeros
-   *   
-   * The default value is 0x10
-   * 
- */ - volatile uint32_t tx_mux; - -} dsp_tx_regs_t; - -#define dsp_tx_regs ((dsp_tx_regs_t *) _SR_ADDR(SR_TX_DSP)) - -// --- VITA RX CTRL regs --- -typedef struct { - // The following 3 are logically a single command register. - // They are clocked into the underlying fifo when time_ticks is written. - volatile uint32_t cmd; // {now, chain, num_samples(30) - volatile uint32_t time_secs; - volatile uint32_t time_ticks; - - volatile uint32_t clear_overrun; // write anything to clear overrun - volatile uint32_t vrt_header; // word 0 of packet. FPGA fills in packet counter - volatile uint32_t vrt_stream_id; // word 1 of packet. - volatile uint32_t vrt_trailer; - volatile uint32_t nsamples_per_pkt; - volatile uint32_t nchannels; // 1 in basic case, up to 4 for vector sources - volatile uint32_t pad[7]; // Make each structure 16 elements long -} sr_rx_ctrl_t; - -#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL)) - -// --- dsp rx regs --- -#define MIN_CIC_DECIM 1 -#define MAX_CIC_DECIM 128 - -typedef struct { - volatile int32_t freq; - volatile uint32_t scale_iq; // {scale_i,scale_q} - volatile uint32_t decim_rate; - volatile uint32_t dcoffset_i; // Bit 31 high sets fixed offset mode, using lower 14 bits, - // otherwise it is automatic - volatile uint32_t dcoffset_q; // Bit 31 high sets fixed offset mode, using lower 14 bits - - /*! - * \brief input mux configuration. - * - * This determines which ADC (or constant zero) is connected to - * each DDC input. There are N DDCs (1 now). Each has two inputs. - * - *
-   * Mux value:
-   *
-   *    3                   2                   1                       
-   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   * +-------+-------+-------+-------+-------+-------+-------+-------+
-   * |                                                       |Q0 |I0 |
-   * +-------+-------+-------+-------+-------+-------+-------+-------+
-   *
-   * Each 2-bit I field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
-   * Each 2-bit Q field is either 00 (A/D A), 01 (A/D B) or 1X (const zero)
-   *
-   * The default value is 0x4
-   * 
- */ - volatile uint32_t rx_mux; // called adc_mux in dsp_core_rx.v - - /*! - * \brief Streaming GPIO configuration - * - * This determines whether the LSBs of I and Q samples come from the DSP - * pipeline or from the io_rx GPIO pins. To stream GPIO, one must first - * set the GPIO data direction register to have io_rx[15] and/or io_rx[14] - * configured as inputs. The GPIO pins will be sampled at the time the - * remainder of the DSP sample is strobed into the RX sample FIFO. There - * will be a decimation-dependent fixed time offset between the GPIO - * sample stream and the associated RF samples. - * - * 3 2 1 - * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * | MBZ |Q|I| - * +-------+-------+-------+-------+-------+-------+-------+-------+ - * - * I 0=LSB comes from DSP pipeline (default) - * 1=LSB comes from io_rx[15] - * - * Q 0=LSB comes from DSP pipeline (default) - * 1=LSB comes from io_rx[14] - */ - volatile uint32_t gpio_stream_enable; - -} dsp_rx_regs_t; - -#define dsp_rx_regs ((dsp_rx_regs_t *) _SR_ADDR(SR_RX_DSP)) - -// ---------------------------------------------------------------- -// VITA49 64 bit time (write only) - /*! - * \brief Time 64 flags - * - *
-   *
-   *    3                   2                   1                       
-   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-   * +-----------------------------------------------------------+-+-+
-   * |                                                           |S|P|
-   * +-----------------------------------------------------------+-+-+
-   *
-   * P - PPS edge selection (0=negedge, 1=posedge, default=0)
-   * S - Source (0=sma, 1=mimo, 0=default)
-   *
-   * 
- */ -typedef struct { - volatile uint32_t secs; // value to set absolute secs to on next PPS - volatile uint32_t ticks; // value to set absolute ticks to on next PPS - volatile uint32_t flags; // flags - see chart above - volatile uint32_t imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0) -} sr_time64_t; - -#define sr_time64 ((sr_time64_t *) _SR_ADDR(SR_TIME64)) - - -/* - * --- ethernet tx protocol engine regs (write only) --- - * - * These registers control the transmit portion of the ethernet - * protocol engine (out of USRP2). The protocol engine handles fifo - * status and sequence number insertion in outgoing packets, and - * automagically generates status packets when required to inform the - * host of changes in fifo availability. - * - * All outgoing packets have their fifo_status field set to the number - * of 32-bit lines of fifo available in the ethernet Rx fifo (see - * usrp2_eth_packet.h). Seqno's are set if FIXME, else 0. - * - * FIXME clean this up once we know how it's supposed to behave. - */ - -typedef struct { - volatile uint32_t flags; // not yet fully defined (channel?) - volatile uint32_t mac_dst0123; // 4 bytes of destination mac addr - volatile uint32_t mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr - volatile uint32_t mac_src2345; // 4 bytes of destination mac addr - volatile uint32_t seqno; // Write to init seqno. It autoincs on match -} tx_proto_engine_regs_t; - -#define tx_proto_engine ((tx_proto_engine_regs_t *) TX_PROTOCOL_ENGINE_BASE) - -/* - * --- ethernet rx protocol engine regs (write only) --- - * - * These registers control the receive portion of the ethernet - * protocol engine (into USRP2). The protocol engine offloads common - * packet inspection operations so that firmware has less to do on - * "fast path" packets. - * - * The registers define conditions which must be matched for a packet - * to be considered a "fast path" packet. If a received packet - * matches the src and dst mac address, ethertype, flags field, and - * expected seqno number it is considered a "fast path" packet, and - * the expected seqno is updated. If the packet fails to satisfy any - * of the above conditions it's a "slow path" packet, and the - * corresponding SLOWPATH flag will be set buffer_status register. - */ - -typedef struct { - volatile uint32_t flags; // not yet fully defined (channel?) - volatile uint32_t mac_dst0123; // 4 bytes of destination mac addr - volatile uint32_t mac_dst45src01; // 2 bytes of dest mac addr; 2 bytes of src mac addr - volatile uint32_t mac_src2345; // 4 bytes of destination mac addr - volatile uint32_t ethertype_pad; // ethertype in high 16-bits -} rx_proto_engine_regs_t; - -#define rx_proto_engine ((rx_proto_engine_regs_t *) RX_PROTOCOL_ENGINE_BASE) - - - -/////////////////////////////////////////////////// -// Simple Programmable Interrupt Controller, Slave 8 - -#define PIC_BASE 0xD800 - -// Interrupt request lines -// Bit numbers (LSB == 0) that correpond to interrupts into PIC - -#define IRQ_BUFFER 0 // buffer manager -#define IRQ_ONETIME 1 -#define IRQ_SPI 2 -#define IRQ_I2C 3 -#define IRQ_PHY 4 // ethernet PHY -#define IRQ_UNDERRUN 5 -#define IRQ_OVERRUN 6 -#define IRQ_PPS 7 // pulse per second -#define IRQ_UART_RX 8 -#define IRQ_UART_TX 9 -#define IRQ_SERDES 10 -#define IRQ_CLKSTATUS 11 -#define IRQ_PERIODIC 12 - -#define IRQ_TO_MASK(x) (1 << (x)) - -#define PIC_BUFFER_INT IRQ_TO_MASK(IRQ_BUFFER) -#define PIC_ONETIME_INT IRQ_TO_MASK(IRQ_ONETIME) -#define PIC_SPI_INT IRQ_TO_MASK(IRQ_SPI) -#define PIC_I2C_INT IRQ_TO_MASK(IRQ_I2C) -#define PIC_PHY_INT IRQ_TO_MASK(IRQ_PHY) -#define PIC_UNDERRUN_INT IRQ_TO_MASK(IRQ_UNDERRUN) -#define PIC_OVERRUN_INT IRQ_TO_MASK(IRQ_OVERRUN) -#define PIC_PPS_INT IRQ_TO_MASK(IRQ_PPS) -#define PIC_UART_RX_INT IRQ_TO_MASK(IRQ_UART_RX) -#define PIC_UART_TX_INT IRQ_TO_MASK(IRQ_UART_TX) -#define PIC_SERDES IRQ_TO_MASK(IRQ_SERDES) -#define PIC_CLKSTATUS IRQ_TO_MASK(IRQ_CLKSTATUS) - -typedef struct { - volatile uint32_t edge_enable; // mask: 1 -> edge triggered, 0 -> level - volatile uint32_t polarity; // mask: 1 -> rising edge - volatile uint32_t mask; // mask: 1 -> disabled - volatile uint32_t pending; // mask: 1 -> pending; write 1's to clear pending ints -} pic_regs_t; - -#define pic_regs ((pic_regs_t *) PIC_BASE) - -// ---------------------------------------------------------------- -// WB_CLK_RATE is the time base for this -typedef struct { - volatile uint32_t onetime; // Number of wb clk cycles till the onetime interrupt - volatile uint32_t periodic; // Repeat rate of periodic interrupt -} sr_simple_timer_t; - -#define sr_simple_timer ((sr_simple_timer_t *) _SR_ADDR(SR_SIMTIMER)) - -/////////////////////////////////////////////////// -// UART, Slave 10 - -#define UART_BASE 0xE000 - -typedef struct { - // All elements are 8 bits except for clkdiv (16), but we use uint32 to make - // the hardware for decoding easier - volatile uint32_t clkdiv; // Set to 50e6 divided by baud rate (no x16 factor) - volatile uint32_t txlevel; // Number of spaces in the FIFO for writes - volatile uint32_t rxlevel; // Number of available elements in the FIFO for reads - volatile uint32_t txchar; // Write characters to be sent here - volatile uint32_t rxchar; // Read received characters here -} uart_regs_t; - -#define uart_regs ((uart_regs_t *) UART_BASE) - -/////////////////////////////////////////////////// -// ATR Controller, Slave 11 - -#define ATR_BASE 0xE400 - -typedef struct { - volatile uint32_t v[16]; -} atr_regs_t; - -#define ATR_IDLE 0x0 // indicies into v -#define ATR_TX 0x1 -#define ATR_RX 0x2 -#define ATR_FULL 0x3 - -#define atr_regs ((atr_regs_t *) ATR_BASE) - -/////////////////////////////////////////////////// -// SD Card SPI interface, Slave 13 -// All regs are 8 bits wide, but are accessed as if they are 32 bits - -#define SDSPI_BASE 0xEC00 - -typedef struct { - volatile uint32_t status; // Write a 1 or 0 for controlling CS - volatile uint32_t clkdiv; - volatile uint32_t send_dat; - volatile uint32_t receive_dat; -} sdspi_regs_t; - -#define sdspi_regs ((sdspi_regs_t *) SDSPI_BASE) - -/////////////////////////////////////////////////// -// External RAM interface, Slave 14 -// Pages are 1K. Page is 10 bits, set by a control register -// output_regs->ram_page - -#define EXTRAM_BASE 0xF000 -#define extram ((volatile uint32_t *) EXTRAM_BASE) - - -/////////////////////////////////////////////////// - -#endif - diff --git a/firmware/microblaze/lib/sd.c b/firmware/microblaze/lib/sd.c deleted file mode 100644 index d000b28ae..000000000 --- a/firmware/microblaze/lib/sd.c +++ /dev/null @@ -1,197 +0,0 @@ -/* -*- c -*- */ -/* - * Copyright 2008 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 "sd.h" -#include "memory_map.h" -#include "stdint.h" -#include "stdio.h" - -static inline void -sd_packarg(unsigned char *argument,unsigned int value) -{ - argument[3] = (unsigned char)(value >> 24); - argument[2] = (unsigned char)(value >> 16); - argument[1] = (unsigned char)(value >> 8); - argument[0] = (unsigned char)(value); -} - -int -sd_init(void) -{ - unsigned char response[5]; - unsigned char argument[4]; - int i,j; - - for(i=0;i<4;i++) - argument[i] = 0; - - // Set clock to less than 400 kHz to start out - sdspi_regs->clkdiv = 128; - - // Delay at least 74 cycles - sd_assert_cs(); - for(i = 0; i < 100; i++) - sd_send_byte(SD_IDLE); - sd_deassert_cs(); - - // Initialization Sequence -- CMD0 CMD55 ACMD41 CMD58 - // Put card in idle state - if(sd_send_command(SD_CMD0,SD_CMD0_R,response,argument)==0) - return 0; // Something went wrong in command - - j = 0; - do { - j++; - if(sd_send_command(SD_CMD55,SD_CMD55_R,response,argument)==1) - sd_send_command(SD_ACMD41,SD_ACMD41_R,response,argument); - else - j = SD_IDLE_WAIT_MAX; - } - while(((response[0] & SD_MSK_IDLE) == SD_MSK_IDLE) && (j < SD_IDLE_WAIT_MAX)); - - if(j>= SD_IDLE_WAIT_MAX) // IDLE timeout exceeded, card asleep - return 0; - - // CMD58 reads the SD card capabilities - if(sd_send_command(SD_CMD58,SD_CMD58_R,response,argument)==0) - return 0; // CMD58 FAIL - - if((response[2] & SD_MSK_OCR_33) != SD_MSK_OCR_33) - return 0; // Card doesn't do 3.3V - - //printf("OCR = %x %x %x %x\n",response[0],response[1],response[2],response[3]); - - // Set blocklen here - sd_packarg(argument,SD_BLOCKLEN); - if(sd_send_command(SD_CMD16,SD_CMD16_R,response,argument)==0) - return 0; // Set Blocklen failed - - // Reset back to high speed - sdspi_regs->clkdiv = 4; - //puts("finished init\n"); - return 1; -} - -int sd_send_command(unsigned char cmd,unsigned char response_type, - unsigned char *response,unsigned char *argument) -{ - int i; - char response_length; - unsigned char tmp; - - sd_assert_cs(); - sd_send_byte((cmd & 0x3F) | 0x40); - for(i=3;i>=0;i--) - sd_send_byte(argument[i]); - sd_send_byte(SD_CRC); // Always the same - - response_length = 0; - switch(response_type) - { - case SD_R1: - case SD_R1B: - response_length = 1; - break; - case SD_R2: - response_length = 2; - break; - case SD_R3: - response_length = 5; - break; - default: - break; - } - - // Wait for a response, which will have a 0 start bit - i = 0; - do - { - tmp = sd_rcv_byte(); - i++; - } - while(((tmp & 0x80) != 0) && i < SD_CMD_TIMEOUT); - - if(i>= SD_CMD_TIMEOUT) - { - sd_deassert_cs(); - //puts("cmd send timeout\n"); - return 0; - } - - for(i=response_length-1; i>=0; i--) - { - response[i] = tmp; - tmp = sd_rcv_byte(); - } - i = 0; - if(response_type == SD_R1B) - { - do - { - i++; - tmp = sd_rcv_byte(); - } - while(tmp != SD_IDLE); - sd_send_byte(SD_IDLE); - } - - //puts("send cmd success\n"); - sd_deassert_cs(); - return 1; -} - -int -sd_read_block (unsigned int blockaddr, unsigned char *buf) -{ - unsigned char response[5]; - unsigned char argument[4]; - unsigned int i = 0; - unsigned char tmp; - - blockaddr <<= SD_BLOCKLEN_NBITS; - sd_packarg(argument,blockaddr); - if(sd_send_command(SD_CMD17,SD_CMD17_R,response,argument)==0) - return 0; //Failed READ; - if(response[0] != 0) - return 0; //Misaligned READ - - sd_assert_cs(); - i = 0; - do - { - tmp = sd_rcv_byte(); - i++; - } - while((tmp == 0xFF) && (i < SD_RD_TIMEOUT)); - if((i>= SD_RD_TIMEOUT) ||((tmp & SD_MSK_TOK_DATAERROR) == 0)) - { - sd_send_byte(SD_IDLE); // Send a dummy before quitting - return 0; // Data ERROR - } - for(i=0;i. - */ - -#ifndef INCLUDED_SD_H -#define INCLUDED_SD_H - -#include "memory_map.h" - -#define SD_READY 1 -#define SD_IDLE_WAIT_MAX 100 -#define SD_CMD_TIMEOUT 100 -#define SD_RD_TIMEOUT 1000 - -#define SD_CMD0 0 -#define SD_CMD1 1 -#define SD_CMD9 9 -#define SD_CMD10 10 -#define SD_CMD12 12 -#define SD_CMD13 13 -#define SD_CMD16 16 -#define SD_CMD17 17 -#define SD_CMD18 18 -#define SD_CMD24 24 -#define SD_CMD25 25 -#define SD_CMD27 27 -#define SD_CMD28 28 -#define SD_CMD29 29 -#define SD_CMD30 30 -#define SD_CMD32 32 -#define SD_CMD33 33 -#define SD_CMD38 38 -#define SD_CMD55 55 -#define SD_CMD58 58 -#define SD_CMD59 59 -#define SD_ACMD41 41 -#define SD_IDLE 0xFF -#define SD_CRC 0x95 - -#define SD_R1 1 -#define SD_R1B 2 -#define SD_R2 3 -#define SD_R3 4 - -#define SD_CMD0_R SD_R1 -#define SD_CMD16_R SD_R1 -#define SD_CMD17_R SD_R1 -#define SD_CMD55_R SD_R1 -#define SD_ACMD41_R SD_R1 -#define SD_CMD58_R SD_R3 - -#define SD_BLOCKLEN 512 -#define SD_BLOCKLEN_NBITS 9 - -#define SD_MSK_IDLE 0x01 -#define SD_MSK_OCR_33 0xC0 -#define SD_MSK_TOK_DATAERROR 0xE0 - - -int sd_init(void); - -static inline void -sd_assert_cs(void) -{ - // Wait for idle before doing anything - while(sdspi_regs->status != SD_READY) - ; - sdspi_regs->status = 1; -} - -static inline void -sd_deassert_cs(void) -{ - // Wait for idle before doing anything - while(sdspi_regs->status != SD_READY) - ; - sdspi_regs->status = 0; -} - -static inline char -sd_rcv_byte(void) -{ - // Wait for idle before doing anything - while(sdspi_regs->status != SD_READY) - ; - sdspi_regs->send_dat = SD_IDLE; - while(sdspi_regs->status != SD_READY) - ; - return sdspi_regs-> receive_dat; -} - -static inline void -sd_send_byte(char dat) -{ - // Wait for idle before doing anything - while(sdspi_regs->status != SD_READY) - ; // Wait for status = 1 (ready) - sdspi_regs->send_dat = dat; -} - - -int sd_send_command(unsigned char cmd,unsigned char response_type, - unsigned char *response,unsigned char *argument); - -int sd_read_block (unsigned int blockaddr, unsigned char *buf); -int sd_write_block(unsigned int blockaddr, const unsigned char *buf); - -#endif /* INCLUDED_SD_H */ diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp new file mode 100644 index 000000000..071ba0cd2 --- /dev/null +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -0,0 +1,94 @@ +// +// 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 "usrp2_regs.hpp" + +int sr_addr(int misc_output_base, int sr) { + return misc_output_base + 4 * sr; +} + +usrp2_regs_t usrp2_get_regs(int hw_rev) { + + //how about you just make this dependent on hw_rev instead of doing the init before main, and give up the const globals, since the application won't ever need both. + const int misc_output_base = (hw_rev>=USRP2P_FIRST_HW_REV) ? USRP2P_MISC_OUTPUT_BASE : USRP2_MISC_OUTPUT_BASE, + gpio_base = (hw_rev>=USRP2P_FIRST_HW_REV) ? USRP2P_GPIO_BASE : USRP2_GPIO_BASE, + atr_base = (hw_rev>=USRP2P_FIRST_HW_REV) ? USRP2P_ATR_BASE : USRP2_ATR_BASE, + bp_base = (hw_rev>=USRP2P_FIRST_HW_REV) ? USRP2P_BP_STATUS_BASE : USRP2_BP_STATUS_BASE; + + usrp2_regs_t x; + x.sr_misc = 0; + x.sr_tx_prot_eng = 32; + x.sr_rx_prot_eng = 48; + x.sr_buffer_pool_ctrl = 64; + x.sr_udp_sm = 96; + x.sr_tx_dsp = 208; + x.sr_tx_ctrl = 224; + x.sr_rx_dsp = 160; + x.sr_rx_ctrl = 176; + x.sr_time64 = 192; + x.sr_simtimer = 198; + x.sr_last = 255; + x.misc_ctrl_clock = sr_addr(misc_output_base, 0); + x.misc_ctrl_serdes = sr_addr(misc_output_base, 1); + x.misc_ctrl_adc = sr_addr(misc_output_base, 2); + x.misc_ctrl_leds = sr_addr(misc_output_base, 3); + x.misc_ctrl_phy = sr_addr(misc_output_base, 4); + x.misc_ctrl_dbg_mux = sr_addr(misc_output_base, 5); + x.misc_ctrl_ram_page = sr_addr(misc_output_base, 6); + x.misc_ctrl_flush_icache = sr_addr(misc_output_base, 7); + x.misc_ctrl_led_src = sr_addr(misc_output_base, 8); + x.time64_secs = sr_addr(misc_output_base, x.sr_time64 + 0); + x.time64_ticks = sr_addr(misc_output_base, x.sr_time64 + 1); + x.time64_flags = sr_addr(misc_output_base, x.sr_time64 + 2); + x.time64_imm = sr_addr(misc_output_base, x.sr_time64 + 3); + x.time64_tps = sr_addr(misc_output_base, x.sr_time64 + 4); + x.time64_secs_rb = bp_base + 4*10; + x.time64_ticks_rb = bp_base + 4*11; + x.dsp_tx_freq = sr_addr(misc_output_base, x.sr_tx_dsp + 0); + x.dsp_tx_scale_iq = sr_addr(misc_output_base, x.sr_tx_dsp + 1); + x.dsp_tx_interp_rate = sr_addr(misc_output_base, x.sr_tx_dsp + 2); + x.dsp_tx_mux = sr_addr(misc_output_base, x.sr_tx_dsp + 4); + x.dsp_rx_freq = sr_addr(misc_output_base, x.sr_rx_dsp + 0); + x.dsp_rx_scale_iq = sr_addr(misc_output_base, x.sr_rx_dsp + 1); + x.dsp_rx_decim_rate = sr_addr(misc_output_base, x.sr_rx_dsp + 2); + x.dsp_rx_dcoffset_i = sr_addr(misc_output_base, x.sr_rx_dsp + 3); + x.dsp_rx_dcoffset_q = sr_addr(misc_output_base, x.sr_rx_dsp + 4); + x.dsp_rx_mux = sr_addr(misc_output_base, x.sr_rx_dsp + 5); + x.gpio_io = gpio_base + 0; + x.gpio_ddr = gpio_base + 4; + x.gpio_tx_sel = gpio_base + 8; + x.gpio_rx_sel = gpio_base + 12; + x.atr_idle_txside = atr_base + 0; + x.atr_idle_rxside = atr_base + 2; + x.atr_intx_txside = atr_base + 4; + x.atr_intx_rxside = atr_base + 6; + x.atr_inrx_txside = atr_base + 8; + x.atr_inrx_rxside = atr_base + 10; + x.atr_full_txside = atr_base + 12; + x.atr_full_rxside = atr_base + 14; + x.rx_ctrl_stream_cmd = sr_addr(misc_output_base, x.sr_rx_ctrl + 0); + x.rx_ctrl_time_secs = sr_addr(misc_output_base, x.sr_rx_ctrl + 1); + x.rx_ctrl_time_ticks = sr_addr(misc_output_base, x.sr_rx_ctrl + 2); + x.rx_ctrl_clear_overrun = sr_addr(misc_output_base, x.sr_rx_ctrl + 3); + x.rx_ctrl_vrt_header = sr_addr(misc_output_base, x.sr_rx_ctrl + 4); + x.rx_ctrl_vrt_stream_id = sr_addr(misc_output_base, x.sr_rx_ctrl + 5); + x.rx_ctrl_vrt_trailer = sr_addr(misc_output_base, x.sr_rx_ctrl + 6); + x.rx_ctrl_nsamps_per_pkt = sr_addr(misc_output_base, x.sr_rx_ctrl + 7); + x.rx_ctrl_nchannels = sr_addr(misc_output_base, x.sr_rx_ctrl + 8); + + return x; +} diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 1a5864c85..0ebce6a85 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -18,6 +18,88 @@ #ifndef INCLUDED_USRP2_REGS_HPP #define INCLUDED_USRP2_REGS_HPP +//these are used to set the + +#define USRP2_MISC_OUTPUT_BASE 0xD400 +#define USRP2_GPIO_BASE 0xC800 +#define USRP2_ATR_BASE 0xE400 +#define USRP2_BP_STATUS_BASE 0xCC00 + +#define USRP2P_MISC_OUTPUT_BASE 0x2000 +#define USRP2P_GPIO_BASE 0x3200 +#define USRP2P_ATR_BASE 0x3800 +#define USRP2P_BP_STATUS_BASE 0x3300 + +#define USRP2P_FIRST_HW_REV 0x0A00 + +typedef struct { + int sr_misc; + int sr_tx_prot_eng; + int sr_rx_prot_eng; + int sr_buffer_pool_ctrl; + int sr_udp_sm; + int sr_tx_dsp; + int sr_tx_ctrl; + int sr_rx_dsp; + int sr_rx_ctrl; + int sr_time64; + int sr_simtimer; + int sr_last; + int misc_ctrl_clock; + int misc_ctrl_serdes; + int misc_ctrl_adc; + int misc_ctrl_leds; + int misc_ctrl_phy; + int misc_ctrl_dbg_mux; + int misc_ctrl_ram_page; + int misc_ctrl_flush_icache; + int misc_ctrl_led_src; + int time64_secs; // value to set absolute secs to on next PPS + int time64_ticks; // value to set absolute ticks to on next PPS + int time64_flags; // flags -- see chart below + int time64_imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0) + int time64_tps; // ticks per second rollover count + int time64_secs_rb; + int time64_ticks_rb; + int dsp_tx_freq; + int dsp_tx_scale_iq; + int dsp_tx_interp_rate; + int dsp_tx_mux; + int dsp_rx_freq; + int dsp_rx_scale_iq; + int dsp_rx_decim_rate; + int dsp_rx_dcoffset_i; + int dsp_rx_dcoffset_q; + int dsp_rx_mux; + int gpio_base; + int gpio_io; + int gpio_ddr; + int gpio_tx_sel; + int gpio_rx_sel; + int atr_base; + int atr_idle_txside; + int atr_idle_rxside; + int atr_intx_txside; + int atr_intx_rxside; + int atr_inrx_txside; + int atr_inrx_rxside; + int atr_full_txside; + int atr_full_rxside; + int rx_ctrl_stream_cmd; + int rx_ctrl_time_secs; + int rx_ctrl_time_ticks; + int rx_ctrl_clear_overrun; + int rx_ctrl_vrt_header; + int rx_ctrl_vrt_stream_id; + int rx_ctrl_vrt_trailer; + int rx_ctrl_nsamps_per_pkt; + int rx_ctrl_nchannels; +} usrp2_regs_t; + +extern const usrp2_regs_t usrp2_regs; //the register definitions, set in usrp2_regs.cpp and usrp2p_regs.cpp + +usrp2_regs_t usrp2_get_regs(int hw_rev); + //////////////////////////////////////////////////// // Settings Bus, Slave #7, Not Byte Addressable! // @@ -25,27 +107,12 @@ // 1KB of address space (== 256 32-bit write-only regs) -#define MISC_OUTPUT_BASE 0xD400 +//#define MISC_OUTPUT_BASE 0xD400 //#define TX_PROTOCOL_ENGINE_BASE 0xD480 //#define RX_PROTOCOL_ENGINE_BASE 0xD4C0 //#define BUFFER_POOL_CTRL_BASE 0xD500 //#define LAST_SETTING_REG 0xD7FC // last valid setting register -#define SR_MISC 0 -#define SR_TX_PROT_ENG 32 -#define SR_RX_PROT_ENG 48 -#define SR_BUFFER_POOL_CTRL 64 -#define SR_UDP_SM 96 -#define SR_TX_DSP 208 -#define SR_TX_CTRL 224 -#define SR_RX_DSP 160 -#define SR_RX_CTRL 176 -#define SR_TIME64 192 -#define SR_SIMTIMER 198 -#define SR_LAST 255 - -#define _SR_ADDR(sr) ((MISC_OUTPUT_BASE) + (4*(sr))) - ///////////////////////////////////////////////// // SPI Slave Constants //////////////////////////////////////////////// @@ -58,20 +125,11 @@ #define SPI_SS_TX_DAC 32 #define SPI_SS_TX_ADC 64 #define SPI_SS_TX_DB 128 +#define SPI_SS_ADS62P44 256 //for usrp2p ///////////////////////////////////////////////// // Misc Control //////////////////////////////////////////////// -#define U2_REG_MISC_CTRL_CLOCK _SR_ADDR(0) -#define U2_REG_MISC_CTRL_SERDES _SR_ADDR(1) -#define U2_REG_MISC_CTRL_ADC _SR_ADDR(2) -#define U2_REG_MISC_CTRL_LEDS _SR_ADDR(3) -#define U2_REG_MISC_CTRL_PHY _SR_ADDR(4) // LSB is reset line to eth phy -#define U2_REG_MISC_CTRL_DBG_MUX _SR_ADDR(5) -#define U2_REG_MISC_CTRL_RAM_PAGE _SR_ADDR(6) // FIXME should go somewhere else... -#define U2_REG_MISC_CTRL_FLUSH_ICACHE _SR_ADDR(7) // Flush the icache -#define U2_REG_MISC_CTRL_LED_SRC _SR_ADDR(8) // HW or SW control for LEDs - #define U2_FLAG_MISC_CTRL_SERDES_ENABLE 8 #define U2_FLAG_MISC_CTRL_SERDES_PRBSEN 4 #define U2_FLAG_MISC_CTRL_SERDES_LOOPEN 2 @@ -99,14 +157,6 @@ * * */ -#define U2_REG_TIME64_SECS _SR_ADDR(SR_TIME64 + 0) // value to set absolute secs to on next PPS -#define U2_REG_TIME64_TICKS _SR_ADDR(SR_TIME64 + 1) // value to set absolute ticks to on next PPS -#define U2_REG_TIME64_FLAGS _SR_ADDR(SR_TIME64 + 2) // flags - see chart above -#define U2_REG_TIME64_IMM _SR_ADDR(SR_TIME64 + 3) // set immediate (0=latch on next pps, 1=latch immediate, default=0) -#define U2_REG_TIME64_TPS _SR_ADDR(SR_TIME64 + 4) // the ticks per second rollover count - -#define U2_REG_TIME64_SECS_RB (0xCC00 + 4*10) -#define U2_REG_TIME64_TICKS_RB (0xCC00 + 4*11) //pps flags (see above) #define U2_FLAG_TIME64_PPS_NEGEDGE (0 << 0) @@ -120,9 +170,6 @@ ///////////////////////////////////////////////// // DSP TX Regs //////////////////////////////////////////////// -#define U2_REG_DSP_TX_FREQ _SR_ADDR(SR_TX_DSP + 0) -#define U2_REG_DSP_TX_SCALE_IQ _SR_ADDR(SR_TX_DSP + 1) // {scale_i,scale_q} -#define U2_REG_DSP_TX_INTERP_RATE _SR_ADDR(SR_TX_DSP + 2) /*! * \brief output mux configuration. @@ -158,17 +205,11 @@ * The default value is 0x10 * */ -#define U2_REG_DSP_TX_MUX _SR_ADDR(SR_TX_DSP + 4) ///////////////////////////////////////////////// // DSP RX Regs //////////////////////////////////////////////// -#define U2_REG_DSP_RX_FREQ _SR_ADDR(SR_RX_DSP + 0) -#define U2_REG_DSP_RX_SCALE_IQ _SR_ADDR(SR_RX_DSP + 1) // {scale_i,scale_q} -#define U2_REG_DSP_RX_DECIM_RATE _SR_ADDR(SR_RX_DSP + 2) -#define U2_REG_DSP_RX_DCOFFSET_I _SR_ADDR(SR_RX_DSP + 3) // Bit 31 high sets fixed offset mode, using lower 14 bits, - // otherwise it is automatic -#define U2_REG_DSP_RX_DCOFFSET_Q _SR_ADDR(SR_RX_DSP + 4) // Bit 31 high sets fixed offset mode, using lower 14 bits + /*! * \brief input mux configuration. * @@ -190,20 +231,10 @@ * The default value is 0x4 * */ -#define U2_REG_DSP_RX_MUX _SR_ADDR(SR_RX_DSP + 5) // called adc_mux in dsp_core_rx.v //////////////////////////////////////////////// // GPIO, Slave 4 //////////////////////////////////////////////// -// -// These go to the daughterboard i/o pins -// -#define U2_REG_GPIO_BASE 0xC800 - -#define U2_REG_GPIO_IO U2_REG_GPIO_BASE + 0 // 32 bits, gpio io pins (tx high 16 bits, rx low 16 bits) -#define U2_REG_GPIO_DDR U2_REG_GPIO_BASE + 4 // 32 bits, gpio ddr, 1 means output (tx high 16 bits, rx low 16 bits) -#define U2_REG_GPIO_TX_SEL U2_REG_GPIO_BASE + 8 // 16 2-bit fields select which source goes to TX DB -#define U2_REG_GPIO_RX_SEL U2_REG_GPIO_BASE + 12 // 16 2-bit fields select which source goes to RX DB // each 2-bit sel field is layed out this way #define U2_FLAG_GPIO_SEL_GPIO 0 // if pin is an output, set by GPIO register @@ -214,31 +245,11 @@ /////////////////////////////////////////////////// // ATR Controller, Slave 11 //////////////////////////////////////////////// -#define U2_REG_ATR_BASE 0xE400 -#define U2_REG_ATR_IDLE_TXSIDE U2_REG_ATR_BASE + 0 -#define U2_REG_ATR_IDLE_RXSIDE U2_REG_ATR_BASE + 2 -#define U2_REG_ATR_INTX_TXSIDE U2_REG_ATR_BASE + 4 -#define U2_REG_ATR_INTX_RXSIDE U2_REG_ATR_BASE + 6 -#define U2_REG_ATR_INRX_TXSIDE U2_REG_ATR_BASE + 8 -#define U2_REG_ATR_INRX_RXSIDE U2_REG_ATR_BASE + 10 -#define U2_REG_ATR_FULL_TXSIDE U2_REG_ATR_BASE + 12 -#define U2_REG_ATR_FULL_RXSIDE U2_REG_ATR_BASE + 14 /////////////////////////////////////////////////// // VITA RX CTRL regs /////////////////////////////////////////////////// -// The following 3 are logically a single command register. -// They are clocked into the underlying fifo when time_ticks is written. -#define U2_REG_RX_CTRL_STREAM_CMD _SR_ADDR(SR_RX_CTRL + 0) // {now, chain, num_samples(30) -#define U2_REG_RX_CTRL_TIME_SECS _SR_ADDR(SR_RX_CTRL + 1) -#define U2_REG_RX_CTRL_TIME_TICKS _SR_ADDR(SR_RX_CTRL + 2) - -#define U2_REG_RX_CTRL_CLEAR_OVERRUN _SR_ADDR(SR_RX_CTRL + 3) // write anything to clear overrun -#define U2_REG_RX_CTRL_VRT_HEADER _SR_ADDR(SR_RX_CTRL + 4) // word 0 of packet. FPGA fills in packet counter -#define U2_REG_RX_CTRL_VRT_STREAM_ID _SR_ADDR(SR_RX_CTRL + 5) // word 1 of packet. -#define U2_REG_RX_CTRL_VRT_TRAILER _SR_ADDR(SR_RX_CTRL + 6) -#define U2_REG_RX_CTRL_NSAMPS_PER_PKT _SR_ADDR(SR_RX_CTRL + 7) -#define U2_REG_RX_CTRL_NCHANNELS _SR_ADDR(SR_RX_CTRL + 8) // 1 in basic case, up to 4 for vector sources + #endif /* INCLUDED_USRP2_REGS_HPP */ -- cgit v1.2.3 From 06b0fc51c92a933d2641395c0b3974bb95df18d0 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 27 Jul 2010 19:18:48 -0700 Subject: Ethernet PHY re-do. --- firmware/microblaze/lib/Makefile.inc | 1 - firmware/microblaze/lib/eth_mac.c | 8 - firmware/microblaze/lib/eth_phy.h | 219 ------------------- firmware/microblaze/lib/ethernet.c | 389 --------------------------------- firmware/microblaze/usrp2/Makefile.am | 3 +- firmware/microblaze/usrp2/eth_phy.h | 219 +++++++++++++++++++ firmware/microblaze/usrp2/ethernet.c | 389 +++++++++++++++++++++++++++++++++ firmware/microblaze/usrp2p/Makefile.am | 3 +- firmware/microblaze/usrp2p/eth_phy.h | 210 ++++++++++++++++++ firmware/microblaze/usrp2p/ethernet.c | 388 ++++++++++++++++++++++++++++++++ 10 files changed, 1210 insertions(+), 619 deletions(-) delete mode 100644 firmware/microblaze/lib/eth_phy.h delete mode 100644 firmware/microblaze/lib/ethernet.c create mode 100644 firmware/microblaze/usrp2/eth_phy.h create mode 100644 firmware/microblaze/usrp2/ethernet.c create mode 100644 firmware/microblaze/usrp2p/eth_phy.h create mode 100644 firmware/microblaze/usrp2p/ethernet.c (limited to 'firmware') diff --git a/firmware/microblaze/lib/Makefile.inc b/firmware/microblaze/lib/Makefile.inc index 0e88298b8..02a267d35 100644 --- a/firmware/microblaze/lib/Makefile.inc +++ b/firmware/microblaze/lib/Makefile.inc @@ -25,7 +25,6 @@ COMMON_SRCS = \ $(top_srcdir)/lib/buffer_pool.c \ $(top_srcdir)/lib/dbsm.c \ $(top_srcdir)/lib/eeprom.c \ - $(top_srcdir)/lib/ethernet.c \ $(top_srcdir)/lib/eth_mac.c \ $(top_srcdir)/lib/_exit.c \ $(top_srcdir)/lib/exit.c \ diff --git a/firmware/microblaze/lib/eth_mac.c b/firmware/microblaze/lib/eth_mac.c index 375d3f4d4..cd0179deb 100644 --- a/firmware/microblaze/lib/eth_mac.c +++ b/firmware/microblaze/lib/eth_mac.c @@ -83,14 +83,6 @@ eth_mac_read_rmon(int addr) int eth_mac_miim_read(int addr) { - if (hwconfig_simulation_p()){ - switch(addr){ - case PHY_LINK_AN: - return LANSR_MASTER | LANSR_LINK_GOOD | LANSR_SPEED_1000; - default: - return 0; - } - } int phy_addr = PHY_ADDR; eth_mac->miiaddress = ((addr & 0x1f) << 8) | phy_addr; diff --git a/firmware/microblaze/lib/eth_phy.h b/firmware/microblaze/lib/eth_phy.h deleted file mode 100644 index 6c16f97b7..000000000 --- a/firmware/microblaze/lib/eth_phy.h +++ /dev/null @@ -1,219 +0,0 @@ -/* -*- c -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * 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 . - */ - -/* Much of this was extracted from the Linux e1000_hw.h file */ - -#ifndef INCLUDED_ETH_PHY_H -#define INCLUDED_ETH_PHY_H - -/* PHY 1000 MII Register/Bit Definitions */ -/* PHY Registers defined by IEEE */ - -#define PHY_CTRL 0x00 /* Control Register */ -#define PHY_STATUS 0x01 /* Status Regiser */ -#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ -#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ -#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ -#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ -#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ -#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */ -#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ -#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ -#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ -#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ - -/* PHY 1000 MII Register additions in DP83856 */ -/* The part implements 0x00 thru 0x1f; we use these. */ - -#define PHY_LINK_AN 0x11 /* Link and Auto Negotiation Status Reg */ -#define PHY_INT_STATUS 0x14 /* Interupt Status Reg (RO) */ -#define PHY_INT_MASK 0x15 /* Interrupt Mask Reg (RW) */ -#define PHY_INT_CLEAR 0x17 /* Interrupt Clear Reg (RW) */ - - -/* Bit definitions for some of the registers above */ - -/* PHY Control Register (PHY_CTRL) */ -#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ -#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ -#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ -#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ -#define MII_CR_POWER_DOWN 0x0800 /* Power down */ -#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ -#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ -#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ - -/* PHY Status Register (PHY_STATUS) */ -#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ -#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ -#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ -#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ -#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ -#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ -#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ -#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ -#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ -#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ -#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ -#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ -#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ -#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ -#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ - -/* Autoneg Advertisement Register (PHY_AUTONEG_ADV) */ -#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ -#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ -#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ -#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ -#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ -#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ -#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ -#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ -#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ -#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Link Partner Ability Register (Base Page) (PHY_LP_ABILITY) */ -#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ -#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ -#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ -#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ -#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ -#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ -#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ -#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ -#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ -#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ -#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Autoneg Expansion Register (PHY_AUTONEG_EXP) */ -#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ -#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ -#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ -#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ -#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */ - -/* Next Page TX Register (PHY_NEXT_PAGE_TX) */ -#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* Link Partner Next Page Register (PHY_LP_NEXT_PAGE) */ -#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ -#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* 1000BASE-T Control Register (PHY_1000T_CTRL) */ -#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ -#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ -#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ -#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ - /* 0=DTE device */ -#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ - /* 0=Configure PHY as Slave */ -#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ - /* 0=Automatic Master/Slave config */ -#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ -#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ -#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ -#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ -#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ - -/* 1000BASE-T Status Register (PHY_1000T_STATUS) */ -#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ -#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ -#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ -#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ -#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ -#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ -#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ -#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ -#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 -#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 -#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 - -/* Extended Status Register (PHY_EXT_STATUS) */ -#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ -#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ -#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ -#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ - -#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */ -#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */ - -#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */ - /* (0=enable, 1=disable) */ - -/* Link and Auto Negotiation Status Reg (PHY_LINK_AN) [READ-ONLY] */ -#define LANSR_MASTER 0x0001 /* 1=PHY is currently in master mode */ -#define LANSR_FULL_DUPLEX 0x0002 /* 1=PHY is currently full duplex */ -#define LANSR_LINK_GOOD 0x0004 /* 1=a good link is established */ -#define LANSR_SPEED_MASK 0x0018 -#define LANSR_SPEED_10 0x0000 /* 10Mb/s */ -#define LANSR_SPEED_100 0x0008 /* 100Mb/s */ -#define LANSR_SPEED_1000 0x0010 /* 1000Mb/s */ -#define LANSR_SPEED_RSRVD 0x0018 /* reserved */ -#define LANSR_NON_COMP_MODE 0x0020 /* 1=detects only in non-compliant mode */ -#define LANSR_DEEP_LOOPBACK 0x0040 /* 1=the PHY operates in deep loopback mode */ -#define LANSR_SHALLOW_LOOPBACK 0x0080 /* 1=the PHY operates in shallow loopback mode */ -#define LANSR_RSRVD_8 0x0100 /* reserved */ -#define LANSR_FIFO_ERR 0x0200 /* 1=FIFO error occurred */ -#define LANSR_MDIX_XOVER 0x0400 /* 1=PHY's MDI is in cross-over mode */ -#define LANSR_RSRVD_11 0x0800 /* resevered */ -#define LANSR_TP_POLARITY_REV 0xf000 /* Twisted pair polarity status A:D([15:12]) 1=reversed */ - -/* Interrupt status, mask and clear regs (PHY_INT_{STATUS,MASK,CLEAR}) */ -#define PHY_INT_RSRVD_0 0x0001 /* reserved */ -#define PHY_INT_RSRVD_1 0x0002 /* reserved */ -#define PHY_INT_RSRVD_2 0x0004 /* reserved */ -#define PHY_INT_REM_FLT_CNG 0x0008 /* Remote Fault Changed */ -#define PHY_INT_AN_CMPL 0x0010 /* Auto-negotiation completion */ -#define PHY_INT_NXT_PG_RCVD 0x0020 /* Next Page Received */ -#define PHY_INT_JABBER_CNG 0x0040 /* Jabber Changed */ -#define PHY_INT_NO_LINK 0x0080 /* No link after auto-negotiation */ -#define PHY_INT_NO_HCD 0x0100 /* AN couldn't determine highest common denominator */ -#define PHY_INT_MAS_SLA_ERR 0x0200 /* Master / Slave Error: couldn't resolve */ -#define PHY_INT_PRL_DET_FLT 0x0400 /* Parallel detection fault */ -#define PHY_INT_POL_CNG 0x0800 /* Polarity of any channel changed */ -#define PHY_INT_MDIX_CNG 0x1000 /* MDIX changed. A pair swap occurred. */ -#define PHY_INT_DPLX_CNG 0x2000 /* Duplex changed */ -#define PHY_INT_LNK_CNG 0x4000 /* Link changed (asserted when a link is established or broken) */ -#define PHY_INT_SPD_CNG 0x8000 /* Speed changed */ - -#endif /* INCLUDED_ETH_PHY_H */ diff --git a/firmware/microblaze/lib/ethernet.c b/firmware/microblaze/lib/ethernet.c deleted file mode 100644 index 2d7c4d7bd..000000000 --- a/firmware/microblaze/lib/ethernet.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright 2007 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, see . - */ - -#include "ethernet.h" -#include "memory_map.h" -#include "eth_phy.h" -#include "eth_mac.h" -#include "eth_mac_regs.h" -#include "pic.h" -#include "hal_io.h" -#include "nonstdio.h" -#include -#include "i2c.h" -#include "usrp2/fw_common.h" - -#define VERBOSE 0 - -static ethernet_t ed_state; -static ethernet_link_changed_callback_t ed_callback = 0; - -void -ethernet_register_link_changed_callback(ethernet_link_changed_callback_t new_callback) -{ - ed_callback = new_callback; -} - - -static void -ed_set_mac_speed(int speed) -{ - printf("Speed set to %d\n",speed); - /* - switch(speed){ - case 10: - eth_mac->speed = 1; - break; - case 100: - eth_mac->speed = 2; - break; - case 1000: - eth_mac->speed = 4; - break; - default: - break; - } - */ -} - -static void -ed_link_up(int speed) -{ - // putstr("ed_link_up: "); puthex16_nl(speed); - - ed_set_mac_speed(speed); - - if (ed_callback) // fire link changed callback - (*ed_callback)(speed); -} - -static void -ed_link_down(void) -{ - // putstr("ed_link_down\n"); - - if (ed_callback) // fire link changed callback - (*ed_callback)(0); -} - - -static void -ed_link_speed_change(int speed) -{ - ed_link_down(); - ed_link_up(speed); -} - -static void -print_flow_control(int flow_control) -{ - static const char *flow_control_msg[4] = { - "NONE", "WE_TX", "WE_RX", "SYMMETRIC" - }; - putstr("ethernet flow control: "); - puts(flow_control_msg[flow_control & 0x3]); -} - -static void -check_flow_control_resolution(void) -{ - static const unsigned char table[16] = { - // index = {local_asm, local_pause, partner_asm, partner_pause} - FC_NONE, FC_NONE, FC_NONE, FC_NONE, - FC_NONE, FC_SYMM, FC_NONE, FC_SYMM, - FC_NONE, FC_NONE, FC_NONE, FC_WE_TX, - FC_NONE, FC_SYMM, FC_WE_RX, FC_SYMM - }; - - int us = eth_mac_miim_read(PHY_AUTONEG_ADV); - int lp = eth_mac_miim_read(PHY_LP_ABILITY); - int index = (((us >> 10) & 0x3) << 2) | ((lp >> 10) & 0x3); - ed_state.flow_control = table[index]; - - if (1) - print_flow_control(ed_state.flow_control); -} - -/* - * Read the PHY state register to determine link state and speed - */ -static void -ed_check_phy_state(void) -{ - int lansr = eth_mac_miim_read(PHY_LINK_AN); - eth_link_state_t new_state = LS_UNKNOWN; - int new_speed = S_UNKNOWN; - - if (VERBOSE){ - putstr("LANSR: "); - puthex16_nl(lansr); - } - - if (lansr & LANSR_LINK_GOOD){ // link's up - if (VERBOSE) - puts(" LINK_GOOD"); - - new_state = LS_UP; - switch (lansr & LANSR_SPEED_MASK){ - case LANSR_SPEED_10: - new_speed = 10; - break; - - case LANSR_SPEED_100: - new_speed = 100; - break; - - case LANSR_SPEED_1000: - new_speed = 1000; - break; - - default: - new_speed = S_UNKNOWN; - break; - } - - check_flow_control_resolution(); - } - else { // link's down - if (VERBOSE) - puts(" NOT LINK_GOOD"); - - new_state = LS_DOWN; - new_speed = S_UNKNOWN; - } - - if (new_state != ed_state.link_state){ - ed_state.link_state = new_state; // remember new state - if (new_state == LS_UP) - ed_link_up(new_speed); - else if (new_state == LS_DOWN) - ed_link_down(); - } - else if (new_state == LS_UP && new_speed != ed_state.link_speed){ - ed_state.link_speed = new_speed; // remember new speed - ed_link_speed_change(new_speed); - } -} - -/* - * This is fired when the ethernet PHY state changes - */ -static void -eth_phy_irq_handler(unsigned irq) -{ - ed_check_phy_state(); - eth_mac_miim_write(PHY_INT_CLEAR, ~0); // clear all ints -} - -void -ethernet_init(void) -{ - eth_mac_init(ethernet_mac_addr()); - - ed_state.link_state = LS_UNKNOWN; - ed_state.link_speed = S_UNKNOWN; - - // initialize MAC registers - // eth_mac->tx_hwmark = 0x1e; - //eth_mac->tx_lwmark = 0x19; - - //eth_mac->crc_chk_en = 1; - //eth_mac->rx_max_length = 2048; - - // configure PAUSE frame stuff - //eth_mac->tx_pause_en = 1; // pay attn to pause frames sent to us - - //eth_mac->pause_quanta_set = 38; // a bit more than 1 max frame 16kb/512 + fudge - //eth_mac->pause_frame_send_en = 1; // enable sending pause frames - - - // setup PHY to interrupt on changes - - unsigned mask = - (PHY_INT_AN_CMPL // auto-neg completed - | PHY_INT_NO_LINK // no link after auto-neg - | PHY_INT_NO_HCD // no highest common denominator - | PHY_INT_MAS_SLA_ERR // couldn't resolve master/slave - | PHY_INT_PRL_DET_FLT // parallel detection fault - | PHY_INT_LNK_CNG // link established or broken - | PHY_INT_SPD_CNG // speed changed - ); - - eth_mac_miim_write(PHY_INT_CLEAR, ~0); // clear all pending interrupts - eth_mac_miim_write(PHY_INT_MASK, mask); // enable the ones we want - - pic_register_handler(IRQ_PHY, eth_phy_irq_handler); - - // Advertise our flow control configuation. - // - // We and the link partner each specify two bits in the base page - // related to autoconfiguration: NWAY_AR_PAUSE and NWAY_AR_ASM_DIR. - // The bits say what a device is "willing" to do, not what may actually - // happen as a result of the negotiation. There are 4 cases: - // - // PAUSE ASM_DIR - // - // 0 0 I have no flow control capability. - // - // 1 0 I both assert and respond to flow control. - // - // 0 1 I assert flow control, but cannot respond. That is, - // I want to be able to send PAUSE frames, but will ignore any - // you send to me. (This is our configuration.) - // - // 1 1 I can both assert and respond to flow control AND I am willing - // to operate symmetrically OR asymmetrically in EITHER direction. - // (We hope the link partner advertises this, otherwise we don't - // get what we want.) - - int t = eth_mac_miim_read(PHY_AUTONEG_ADV); - t &= ~(NWAY_AR_PAUSE | NWAY_AR_ASM_DIR); - t |= NWAY_AR_ASM_DIR; - - // Say we can't to 10BASE-T or 100BASE-TX, half or full duplex - t &= ~(NWAY_AR_10T_HD_CAPS | NWAY_AR_10T_FD_CAPS | NWAY_AR_100TX_HD_CAPS | NWAY_AR_100TX_FD_CAPS); - - eth_mac_miim_write(PHY_AUTONEG_ADV, t); - int r = eth_mac_miim_read(PHY_AUTONEG_ADV); // DEBUG, read back - if (t != r){ - printf("PHY_AUTONEG_ADV: wrote 0x%x, got 0x%x\n", t, r); - } - - // Restart autonegotation. - // We want to ensure that we're advertising our PAUSE capabilities. - t = eth_mac_miim_read(PHY_CTRL); - eth_mac_miim_write(PHY_CTRL, t | MII_CR_RESTART_AUTO_NEG); -} - -static bool -unprogrammed(const void *t, size_t len) -{ - int i; - uint8_t *p = (uint8_t *)t; - bool all_zeros = true; - bool all_ones = true; - for (i = 0; i < len; i++){ - all_zeros &= p[i] == 0x00; - all_ones &= p[i] == 0xff; - } - return all_ones | all_zeros; -} - -//////////////////// MAC Addr Stuff /////////////////////// - -static int8_t src_mac_addr_initialized = false; -static eth_mac_addr_t src_mac_addr = {{ - 0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff - }}; - -const eth_mac_addr_t * -ethernet_mac_addr(void) -{ - if (!src_mac_addr_initialized){ // fetch from eeprom - src_mac_addr_initialized = true; - - // if we're simulating, don't read the EEPROM model, it's REALLY slow - if (hwconfig_simulation_p()) - return &src_mac_addr; - - eth_mac_addr_t tmp; - bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, &tmp, sizeof(tmp)); - if (!ok || unprogrammed(&tmp, sizeof(tmp))){ - // use the default - } - else - src_mac_addr = tmp; - } - - return &src_mac_addr; -} - -bool -ethernet_set_mac_addr(const eth_mac_addr_t *t) -{ - bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t)); - if (ok){ - src_mac_addr = *t; - src_mac_addr_initialized = true; - //eth_mac_set_addr(t); //this breaks the link - } - - return ok; -} - -//////////////////// IP Addr Stuff /////////////////////// - -static int8_t src_ip_addr_initialized = false; -static struct ip_addr src_ip_addr = { - (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0) -}; - - -const struct ip_addr *get_ip_addr(void) -{ - if (!src_ip_addr_initialized){ // fetch from eeprom - src_ip_addr_initialized = true; - - // if we're simulating, don't read the EEPROM model, it's REALLY slow - if (hwconfig_simulation_p()) - return &src_ip_addr; - - struct ip_addr tmp; - bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, &tmp, sizeof(tmp)); - if (!ok || unprogrammed(&tmp, sizeof(tmp))){ - // use the default - } - else - src_ip_addr = tmp; - } - - return &src_ip_addr; -} - -bool set_ip_addr(const struct ip_addr *t){ - bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, t, sizeof(struct ip_addr)); - if (ok){ - src_ip_addr = *t; - src_ip_addr_initialized = true; - } - - return ok; -} - -int -ethernet_check_errors(void) -{ - // these registers are reset when read - - int r = 0; - /* - if (eth_mac_read_rmon(0x05) != 0) - r |= RME_RX_CRC; - if (eth_mac_read_rmon(0x06) != 0) - r |= RME_RX_FIFO_FULL; - if (eth_mac_read_rmon(0x07) != 0) - r |= RME_RX_2SHORT_2LONG; - - if (eth_mac_read_rmon(0x25) != 0) - r |= RME_TX_JAM_DROP; - if (eth_mac_read_rmon(0x26) != 0) - r |= RME_TX_FIFO_UNDER; - if (eth_mac_read_rmon(0x27) != 0) - r |= RME_TX_FIFO_OVER; - */ - return r; -} diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am index 859ded9e5..b45d2481b 100644 --- a/firmware/microblaze/usrp2/Makefile.am +++ b/firmware/microblaze/usrp2/Makefile.am @@ -34,7 +34,8 @@ noinst_LIBRARIES = libusrp2.a libusrp2_a_SOURCES = \ $(COMMON_SRCS) \ clocks.c \ - sd.c + sd.c \ + ethernet.c noinst_PROGRAMS = \ usrp2_txrx_uhd.elf diff --git a/firmware/microblaze/usrp2/eth_phy.h b/firmware/microblaze/usrp2/eth_phy.h new file mode 100644 index 000000000..6c16f97b7 --- /dev/null +++ b/firmware/microblaze/usrp2/eth_phy.h @@ -0,0 +1,219 @@ +/* -*- c -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * 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 . + */ + +/* Much of this was extracted from the Linux e1000_hw.h file */ + +#ifndef INCLUDED_ETH_PHY_H +#define INCLUDED_ETH_PHY_H + +/* PHY 1000 MII Register/Bit Definitions */ +/* PHY Registers defined by IEEE */ + +#define PHY_CTRL 0x00 /* Control Register */ +#define PHY_STATUS 0x01 /* Status Regiser */ +#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ +#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ +#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ +#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ +#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */ +#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ +#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ + +/* PHY 1000 MII Register additions in DP83856 */ +/* The part implements 0x00 thru 0x1f; we use these. */ + +#define PHY_LINK_AN 0x11 /* Link and Auto Negotiation Status Reg */ +#define PHY_INT_STATUS 0x14 /* Interupt Status Reg (RO) */ +#define PHY_INT_MASK 0x15 /* Interrupt Mask Reg (RW) */ +#define PHY_INT_CLEAR 0x17 /* Interrupt Clear Reg (RW) */ + + +/* Bit definitions for some of the registers above */ + +/* PHY Control Register (PHY_CTRL) */ +#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ +#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ +#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ +#define MII_CR_POWER_DOWN 0x0800 /* Power down */ +#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ +#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ + +/* PHY Status Register (PHY_STATUS) */ +#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ +#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ +#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ +#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ +#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ +#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ +#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ +#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ +#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ +#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ +#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ +#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ +#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ +#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ +#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ + +/* Autoneg Advertisement Register (PHY_AUTONEG_ADV) */ +#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ +#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ +#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ +#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ +#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ +#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ +#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ +#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ +#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ +#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ + +/* Link Partner Ability Register (Base Page) (PHY_LP_ABILITY) */ +#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ +#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ +#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ +#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ +#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ +#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ +#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ +#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ +#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ +#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ +#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ + +/* Autoneg Expansion Register (PHY_AUTONEG_EXP) */ +#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ +#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ +#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ +#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ +#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */ + +/* Next Page TX Register (PHY_NEXT_PAGE_TX) */ +#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ +#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges + * of different NP + */ +#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg + * 0 = cannot comply with msg + */ +#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ +#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow + * 0 = sending last NP + */ + +/* Link Partner Next Page Register (PHY_LP_NEXT_PAGE) */ +#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ +#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges + * of different NP + */ +#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg + * 0 = cannot comply with msg + */ +#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ +#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ +#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow + * 0 = sending last NP + */ + +/* 1000BASE-T Control Register (PHY_1000T_CTRL) */ +#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ +#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ +#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ +#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ + /* 0=DTE device */ +#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ + /* 0=Configure PHY as Slave */ +#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ + /* 0=Automatic Master/Slave config */ +#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ +#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ +#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ +#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ +#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ + +/* 1000BASE-T Status Register (PHY_1000T_STATUS) */ +#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ +#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ +#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ +#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ +#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ +#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ +#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ +#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ +#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 +#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 +#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 + +/* Extended Status Register (PHY_EXT_STATUS) */ +#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ +#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ +#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ +#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ + +#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */ +#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */ + +#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */ + /* (0=enable, 1=disable) */ + +/* Link and Auto Negotiation Status Reg (PHY_LINK_AN) [READ-ONLY] */ +#define LANSR_MASTER 0x0001 /* 1=PHY is currently in master mode */ +#define LANSR_FULL_DUPLEX 0x0002 /* 1=PHY is currently full duplex */ +#define LANSR_LINK_GOOD 0x0004 /* 1=a good link is established */ +#define LANSR_SPEED_MASK 0x0018 +#define LANSR_SPEED_10 0x0000 /* 10Mb/s */ +#define LANSR_SPEED_100 0x0008 /* 100Mb/s */ +#define LANSR_SPEED_1000 0x0010 /* 1000Mb/s */ +#define LANSR_SPEED_RSRVD 0x0018 /* reserved */ +#define LANSR_NON_COMP_MODE 0x0020 /* 1=detects only in non-compliant mode */ +#define LANSR_DEEP_LOOPBACK 0x0040 /* 1=the PHY operates in deep loopback mode */ +#define LANSR_SHALLOW_LOOPBACK 0x0080 /* 1=the PHY operates in shallow loopback mode */ +#define LANSR_RSRVD_8 0x0100 /* reserved */ +#define LANSR_FIFO_ERR 0x0200 /* 1=FIFO error occurred */ +#define LANSR_MDIX_XOVER 0x0400 /* 1=PHY's MDI is in cross-over mode */ +#define LANSR_RSRVD_11 0x0800 /* resevered */ +#define LANSR_TP_POLARITY_REV 0xf000 /* Twisted pair polarity status A:D([15:12]) 1=reversed */ + +/* Interrupt status, mask and clear regs (PHY_INT_{STATUS,MASK,CLEAR}) */ +#define PHY_INT_RSRVD_0 0x0001 /* reserved */ +#define PHY_INT_RSRVD_1 0x0002 /* reserved */ +#define PHY_INT_RSRVD_2 0x0004 /* reserved */ +#define PHY_INT_REM_FLT_CNG 0x0008 /* Remote Fault Changed */ +#define PHY_INT_AN_CMPL 0x0010 /* Auto-negotiation completion */ +#define PHY_INT_NXT_PG_RCVD 0x0020 /* Next Page Received */ +#define PHY_INT_JABBER_CNG 0x0040 /* Jabber Changed */ +#define PHY_INT_NO_LINK 0x0080 /* No link after auto-negotiation */ +#define PHY_INT_NO_HCD 0x0100 /* AN couldn't determine highest common denominator */ +#define PHY_INT_MAS_SLA_ERR 0x0200 /* Master / Slave Error: couldn't resolve */ +#define PHY_INT_PRL_DET_FLT 0x0400 /* Parallel detection fault */ +#define PHY_INT_POL_CNG 0x0800 /* Polarity of any channel changed */ +#define PHY_INT_MDIX_CNG 0x1000 /* MDIX changed. A pair swap occurred. */ +#define PHY_INT_DPLX_CNG 0x2000 /* Duplex changed */ +#define PHY_INT_LNK_CNG 0x4000 /* Link changed (asserted when a link is established or broken) */ +#define PHY_INT_SPD_CNG 0x8000 /* Speed changed */ + +#endif /* INCLUDED_ETH_PHY_H */ diff --git a/firmware/microblaze/usrp2/ethernet.c b/firmware/microblaze/usrp2/ethernet.c new file mode 100644 index 000000000..d60d7dc4c --- /dev/null +++ b/firmware/microblaze/usrp2/ethernet.c @@ -0,0 +1,389 @@ +/* + * Copyright 2007 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, see . + */ + +#include "ethernet.h" +#include "memory_map.h" +#include "eth_phy.h" +#include "eth_mac.h" +#include "eth_mac_regs.h" +#include "pic.h" +#include "hal_io.h" +#include "nonstdio.h" +#include +#include "i2c.h" +#include "usrp2/fw_common.h" + +#define VERBOSE 1 + +static ethernet_t ed_state; +static ethernet_link_changed_callback_t ed_callback = 0; + +void +ethernet_register_link_changed_callback(ethernet_link_changed_callback_t new_callback) +{ + ed_callback = new_callback; +} + + +static void +ed_set_mac_speed(int speed) +{ + printf("Speed set to %d\n",speed); + /* + switch(speed){ + case 10: + eth_mac->speed = 1; + break; + case 100: + eth_mac->speed = 2; + break; + case 1000: + eth_mac->speed = 4; + break; + default: + break; + } + */ +} + +static void +ed_link_up(int speed) +{ + // putstr("ed_link_up: "); puthex16_nl(speed); + + ed_set_mac_speed(speed); + + if (ed_callback) // fire link changed callback + (*ed_callback)(speed); +} + +static void +ed_link_down(void) +{ + // putstr("ed_link_down\n"); + + if (ed_callback) // fire link changed callback + (*ed_callback)(0); +} + + +static void +ed_link_speed_change(int speed) +{ + ed_link_down(); + ed_link_up(speed); +} + +static void +print_flow_control(int flow_control) +{ + static const char *flow_control_msg[4] = { + "NONE", "WE_TX", "WE_RX", "SYMMETRIC" + }; + putstr("ethernet flow control: "); + puts(flow_control_msg[flow_control & 0x3]); +} + +static void +check_flow_control_resolution(void) +{ + static const unsigned char table[16] = { + // index = {local_asm, local_pause, partner_asm, partner_pause} + FC_NONE, FC_NONE, FC_NONE, FC_NONE, + FC_NONE, FC_SYMM, FC_NONE, FC_SYMM, + FC_NONE, FC_NONE, FC_NONE, FC_WE_TX, + FC_NONE, FC_SYMM, FC_WE_RX, FC_SYMM + }; + + int us = eth_mac_miim_read(PHY_AUTONEG_ADV); + int lp = eth_mac_miim_read(PHY_LP_ABILITY); + int index = (((us >> 10) & 0x3) << 2) | ((lp >> 10) & 0x3); + ed_state.flow_control = table[index]; + + if (1) + print_flow_control(ed_state.flow_control); +} + +/* + * Read the PHY state register to determine link state and speed + */ +static void +ed_check_phy_state(void) +{ + int lansr = eth_mac_miim_read(PHY_LINK_AN); + eth_link_state_t new_state = LS_UNKNOWN; + int new_speed = S_UNKNOWN; + + if (VERBOSE){ + putstr("LANSR: "); + puthex16_nl(lansr); + } + + if (lansr & LANSR_LINK_GOOD){ // link's up + if (VERBOSE) + puts(" LINK_GOOD"); + + new_state = LS_UP; + switch (lansr & LANSR_SPEED_MASK){ + case LANSR_SPEED_10: + new_speed = 10; + break; + + case LANSR_SPEED_100: + new_speed = 100; + break; + + case LANSR_SPEED_1000: + new_speed = 1000; + break; + + default: + new_speed = S_UNKNOWN; + break; + } + + check_flow_control_resolution(); + } + else { // link's down + if (VERBOSE) + puts(" NOT LINK_GOOD"); + + new_state = LS_DOWN; + new_speed = S_UNKNOWN; + } + + if (new_state != ed_state.link_state){ + ed_state.link_state = new_state; // remember new state + if (new_state == LS_UP) + ed_link_up(new_speed); + else if (new_state == LS_DOWN) + ed_link_down(); + } + else if (new_state == LS_UP && new_speed != ed_state.link_speed){ + ed_state.link_speed = new_speed; // remember new speed + ed_link_speed_change(new_speed); + } +} + +/* + * This is fired when the ethernet PHY state changes + */ +static void +eth_phy_irq_handler(unsigned irq) +{ + ed_check_phy_state(); + eth_mac_miim_write(PHY_INT_CLEAR, ~0); // clear all ints +} + +void +ethernet_init(void) +{ + eth_mac_init(ethernet_mac_addr()); + + ed_state.link_state = LS_UNKNOWN; + ed_state.link_speed = S_UNKNOWN; + + // initialize MAC registers + // eth_mac->tx_hwmark = 0x1e; + //eth_mac->tx_lwmark = 0x19; + + //eth_mac->crc_chk_en = 1; + //eth_mac->rx_max_length = 2048; + + // configure PAUSE frame stuff + //eth_mac->tx_pause_en = 1; // pay attn to pause frames sent to us + + //eth_mac->pause_quanta_set = 38; // a bit more than 1 max frame 16kb/512 + fudge + //eth_mac->pause_frame_send_en = 1; // enable sending pause frames + + + // setup PHY to interrupt on changes + + unsigned mask = + (PHY_INT_AN_CMPL // auto-neg completed + | PHY_INT_NO_LINK // no link after auto-neg + | PHY_INT_NO_HCD // no highest common denominator + | PHY_INT_MAS_SLA_ERR // couldn't resolve master/slave + | PHY_INT_PRL_DET_FLT // parallel detection fault + | PHY_INT_LNK_CNG // link established or broken + | PHY_INT_SPD_CNG // speed changed + ); + + eth_mac_miim_write(PHY_INT_CLEAR, ~0); // clear all pending interrupts + eth_mac_miim_write(PHY_INT_MASK, mask); // enable the ones we want + + pic_register_handler(IRQ_PHY, eth_phy_irq_handler); + + // Advertise our flow control configuation. + // + // We and the link partner each specify two bits in the base page + // related to autoconfiguration: NWAY_AR_PAUSE and NWAY_AR_ASM_DIR. + // The bits say what a device is "willing" to do, not what may actually + // happen as a result of the negotiation. There are 4 cases: + // + // PAUSE ASM_DIR + // + // 0 0 I have no flow control capability. + // + // 1 0 I both assert and respond to flow control. + // + // 0 1 I assert flow control, but cannot respond. That is, + // I want to be able to send PAUSE frames, but will ignore any + // you send to me. (This is our configuration.) + // + // 1 1 I can both assert and respond to flow control AND I am willing + // to operate symmetrically OR asymmetrically in EITHER direction. + // (We hope the link partner advertises this, otherwise we don't + // get what we want.) + + int t = eth_mac_miim_read(PHY_AUTONEG_ADV); + t &= ~(NWAY_AR_PAUSE | NWAY_AR_ASM_DIR); + t |= NWAY_AR_ASM_DIR; + + // Say we can't to 10BASE-T or 100BASE-TX, half or full duplex + t &= ~(NWAY_AR_10T_HD_CAPS | NWAY_AR_10T_FD_CAPS | NWAY_AR_100TX_HD_CAPS | NWAY_AR_100TX_FD_CAPS); + + eth_mac_miim_write(PHY_AUTONEG_ADV, t); + int r = eth_mac_miim_read(PHY_AUTONEG_ADV); // DEBUG, read back + if (t != r){ + printf("PHY_AUTONEG_ADV: wrote 0x%x, got 0x%x\n", t, r); + } + + // Restart autonegotation. + // We want to ensure that we're advertising our PAUSE capabilities. + t = eth_mac_miim_read(PHY_CTRL); + eth_mac_miim_write(PHY_CTRL, t | MII_CR_RESTART_AUTO_NEG); +} + +static bool +unprogrammed(const void *t, size_t len) +{ + int i; + uint8_t *p = (uint8_t *)t; + bool all_zeros = true; + bool all_ones = true; + for (i = 0; i < len; i++){ + all_zeros &= p[i] == 0x00; + all_ones &= p[i] == 0xff; + } + return all_ones | all_zeros; +} + +//////////////////// MAC Addr Stuff /////////////////////// + +static int8_t src_mac_addr_initialized = false; +static eth_mac_addr_t src_mac_addr = {{ + 0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff + }}; + +const eth_mac_addr_t * +ethernet_mac_addr(void) +{ + if (!src_mac_addr_initialized){ // fetch from eeprom + src_mac_addr_initialized = true; + + // if we're simulating, don't read the EEPROM model, it's REALLY slow + if (hwconfig_simulation_p()) + return &src_mac_addr; + + eth_mac_addr_t tmp; + bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, &tmp, sizeof(tmp)); + if (!ok || unprogrammed(&tmp, sizeof(tmp))){ + // use the default + } + else + src_mac_addr = tmp; + } + + return &src_mac_addr; +} + +bool +ethernet_set_mac_addr(const eth_mac_addr_t *t) +{ + bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t)); + if (ok){ + src_mac_addr = *t; + src_mac_addr_initialized = true; + //eth_mac_set_addr(t); //this breaks the link + } + + return ok; +} + +//////////////////// IP Addr Stuff /////////////////////// + +static int8_t src_ip_addr_initialized = false; +static struct ip_addr src_ip_addr = { + (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0) +}; + + +const struct ip_addr *get_ip_addr(void) +{ + if (!src_ip_addr_initialized){ // fetch from eeprom + src_ip_addr_initialized = true; + + // if we're simulating, don't read the EEPROM model, it's REALLY slow + if (hwconfig_simulation_p()) + return &src_ip_addr; + + struct ip_addr tmp; + bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, &tmp, sizeof(tmp)); + if (!ok || unprogrammed(&tmp, sizeof(tmp))){ + // use the default + } + else + src_ip_addr = tmp; + } + + return &src_ip_addr; +} + +bool set_ip_addr(const struct ip_addr *t){ + bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, t, sizeof(struct ip_addr)); + if (ok){ + src_ip_addr = *t; + src_ip_addr_initialized = true; + } + + return ok; +} + +int +ethernet_check_errors(void) +{ + // these registers are reset when read + + int r = 0; + /* + if (eth_mac_read_rmon(0x05) != 0) + r |= RME_RX_CRC; + if (eth_mac_read_rmon(0x06) != 0) + r |= RME_RX_FIFO_FULL; + if (eth_mac_read_rmon(0x07) != 0) + r |= RME_RX_2SHORT_2LONG; + + if (eth_mac_read_rmon(0x25) != 0) + r |= RME_TX_JAM_DROP; + if (eth_mac_read_rmon(0x26) != 0) + r |= RME_TX_FIFO_UNDER; + if (eth_mac_read_rmon(0x27) != 0) + r |= RME_TX_FIFO_OVER; + */ + return r; +} diff --git a/firmware/microblaze/usrp2p/Makefile.am b/firmware/microblaze/usrp2p/Makefile.am index eff544294..86affc1f3 100644 --- a/firmware/microblaze/usrp2p/Makefile.am +++ b/firmware/microblaze/usrp2p/Makefile.am @@ -49,7 +49,8 @@ libusrp2p_a_SOURCES = \ spif.c \ spi_flash.c \ spi_flash_read.c \ - bootloader_utils.c + bootloader_utils.c \ + ethernet.c noinst_PROGRAMS = \ usrp2p_txrx_uhd.elf \ diff --git a/firmware/microblaze/usrp2p/eth_phy.h b/firmware/microblaze/usrp2p/eth_phy.h new file mode 100644 index 000000000..9328debee --- /dev/null +++ b/firmware/microblaze/usrp2p/eth_phy.h @@ -0,0 +1,210 @@ +/* -*- c -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. + * + * 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 . + */ + +/* Much of this was extracted from the Linux e1000_hw.h file */ + +#ifndef INCLUDED_ETH_PHY_H +#define INCLUDED_ETH_PHY_H + +/* PHY 1000 MII Register/Bit Definitions */ +/* PHY Registers defined by IEEE */ + +#define PHY_CTRL 0x00 /* Control Register */ +#define PHY_STATUS 0x01 /* Status Regiser */ +#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ +#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ +#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ +#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ +#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */ +#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ +#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ + +/* PHY 1000 MII Register additions in ET1011C */ +#define PHY_INT_MASK 24 +#define PHY_INT_STATUS 25 +#define PHY_PHY_STATUS 26 + +/* Bit definitions for some of the registers above */ + +/* PHY Control Register (PHY_CTRL) */ +#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ +#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ +#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ +#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ +#define MII_CR_POWER_DOWN 0x0800 /* Power down */ +#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ +#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ +#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ +#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ + +/* PHY Status Register (PHY_STATUS) */ +#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ +#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ +#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ +#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ +#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ +#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ +#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ +#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ +#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ +#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ +#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ +#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ +#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ +#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ +#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ + +/* Autoneg Advertisement Register (PHY_AUTONEG_ADV) */ +#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ +#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ +#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ +#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ +#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ +#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ +#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ +#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ +#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ +#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ + +/* Link Partner Ability Register (Base Page) (PHY_LP_ABILITY) */ +#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ +#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ +#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ +#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ +#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ +#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ +#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ +#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ +#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ +#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ +#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ + +/* Autoneg Expansion Register (PHY_AUTONEG_EXP) */ +#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ +#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ +#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ +#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ +#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */ + +/* Next Page TX Register (PHY_NEXT_PAGE_TX) */ +#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ +#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges + * of different NP + */ +#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg + * 0 = cannot comply with msg + */ +#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ +#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow + * 0 = sending last NP + */ + +/* Link Partner Next Page Register (PHY_LP_NEXT_PAGE) */ +#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ +#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges + * of different NP + */ +#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg + * 0 = cannot comply with msg + */ +#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ +#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ +#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow + * 0 = sending last NP + */ + +/* 1000BASE-T Control Register (PHY_1000T_CTRL) */ +#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ +#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ +#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ +#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ + /* 0=DTE device */ +#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ + /* 0=Configure PHY as Slave */ +#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ + /* 0=Automatic Master/Slave config */ +#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ +#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ +#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ +#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ +#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ + +/* 1000BASE-T Status Register (PHY_1000T_STATUS) */ +#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ +#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ +#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ +#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ +#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ +#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ +#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ +#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ +#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 +#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 +#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 + +/* Extended Status Register (PHY_EXT_STATUS) */ +#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ +#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ +#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ +#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ + +#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */ +#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */ + +#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */ + /* (0=enable, 1=disable) */ + +/* PHY Status Register (PHY_PHY_STATUS) */ +#define PHYSTAT_ASYMMETRIC (1 << 0) +#define PHYSTAT_PAUSE (1 << 1) +#define PHYSTAT_AUTONEG_EN (1 << 2) +#define PHYSTAT_COLLISION (1 << 3) +#define PHYSTAT_RXSTAT (1 << 4) +#define PHYSTAT_TXSTAT (1 << 5) +#define PHYSTAT_LINK (1 << 6) +#define PHYSTAT_DUPLEX (1 << 7) +#define PHYSTAT_SPEED_MASK ((1 << 8) | (1 << 9)) +#define PHYSTAT_SPEED_1000 (1 << 9) +#define PHYSTAT_SPEED_100 (1 << 8) +#define PHYSTAT_SPEED_10 0 +#define PHYSTAT_POLARITY (1 << 10) +#define PHYSTAT_MDIX (1 << 11) +#define PHYSTAT_AUTONEG_STAT (1 << 12) +#define PHYSTAT_STANDBY (1 << 13) + +/* Interrupt status, mask and clear regs (PHY_INT_{STATUS,MASK,CLEAR}) */ +#define PHY_INT_ENABLE (1 << 0) +#define PHY_INT_DOWNSHIFT (1 << 1) +#define PHY_INT_LINK_STATUS_CHANGE (1 << 2) +#define PHY_INT_RX_STATUS_CHANGE (1 << 3) +#define PHY_INT_FIFO_ERROR (1 << 4) +#define PHY_INT_ERR_CTR_FULL (1 << 5) +#define PHY_INT_NEXT_PAGE_RX (1 << 6) +#define PHY_INT_CRC_ERROR (1 << 7) +#define PHY_INT_AUTONEG_STATUS_CHANGE (1 << 8) +#define PHY_INT_MDIO_SYNC_LOST (1 << 9) +#define PHY_INT_TDR_IP_PHONE (1 << 10) + +#endif /* INCLUDED_ETH_PHY_H */ diff --git a/firmware/microblaze/usrp2p/ethernet.c b/firmware/microblaze/usrp2p/ethernet.c new file mode 100644 index 000000000..134650326 --- /dev/null +++ b/firmware/microblaze/usrp2p/ethernet.c @@ -0,0 +1,388 @@ +/* + * Copyright 2007 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, see . + */ + +//Changes for USRP2P: status registers different (ethernet.h) + +#include "ethernet.h" +#include "memory_map.h" +#include "eth_phy.h" +#include +#include +#include +#include +#include +#include +#include +#include "usrp2/fw_common.h" + +#define VERBOSE 1 + +static ethernet_t ed_state; +static ethernet_link_changed_callback_t ed_callback = 0; + +void +ethernet_register_link_changed_callback(ethernet_link_changed_callback_t new_callback) +{ + ed_callback = new_callback; +} + + +static void +ed_set_mac_speed(int speed) +{ + printf("Speed set to %d\n",speed); + /* + switch(speed){ + case 10: + eth_mac->speed = 1; + break; + case 100: + eth_mac->speed = 2; + break; + case 1000: + eth_mac->speed = 4; + break; + default: + break; + } + */ +} + +static void +ed_link_up(int speed) +{ + // putstr("ed_link_up: "); puthex16_nl(speed); + + ed_set_mac_speed(speed); + + if (ed_callback) // fire link changed callback + (*ed_callback)(speed); +} + +static void +ed_link_down(void) +{ + // putstr("ed_link_down\n"); + + if (ed_callback) // fire link changed callback + (*ed_callback)(0); +} + + +static void +ed_link_speed_change(int speed) +{ + ed_link_down(); + ed_link_up(speed); +} + +static void +print_flow_control(int flow_control) +{ + static const char *flow_control_msg[4] = { + "NONE", "WE_TX", "WE_RX", "SYMMETRIC" + }; + putstr("ethernet flow control: "); + puts(flow_control_msg[flow_control & 0x3]); +} + +static void +check_flow_control_resolution(void) +{ + static const unsigned char table[16] = { + // index = {local_asm, local_pause, partner_asm, partner_pause} + FC_NONE, FC_NONE, FC_NONE, FC_NONE, + FC_NONE, FC_SYMM, FC_NONE, FC_SYMM, + FC_NONE, FC_NONE, FC_NONE, FC_WE_TX, + FC_NONE, FC_SYMM, FC_WE_RX, FC_SYMM + }; + + int us = eth_mac_miim_read(PHY_AUTONEG_ADV); + int lp = eth_mac_miim_read(PHY_LP_ABILITY); + int index = (((us >> 10) & 0x3) << 2) | ((lp >> 10) & 0x3); + ed_state.flow_control = table[index]; + + if (1) + print_flow_control(ed_state.flow_control); +} + +/* + * Read the PHY state register to determine link state and speed + */ +static void +ed_check_phy_state(void) +{ + int phystat = eth_mac_miim_read(PHY_PHY_STATUS); + eth_link_state_t new_state = LS_UNKNOWN; + int new_speed = S_UNKNOWN; + + if (VERBOSE){ + putstr("PHYSTAT: "); + puthex16_nl(phystat); + } + + if (phystat & PHYSTAT_LINK){ // link's up + if (VERBOSE) + puts(" LINK_GOOD"); + + new_state = LS_UP; + switch (phystat & PHYSTAT_SPEED_MASK){ + case PHYSTAT_SPEED_10: + new_speed = 10; + break; + + case PHYSTAT_SPEED_100: + new_speed = 100; + break; + + case PHYSTAT_SPEED_1000: + new_speed = 1000; + break; + + default: + new_speed = S_UNKNOWN; + break; + } + + check_flow_control_resolution(); + } + else { // link's down + if (VERBOSE) + puts(" NOT LINK_GOOD"); + + new_state = LS_DOWN; + new_speed = S_UNKNOWN; + } + + if (new_state != ed_state.link_state){ + ed_state.link_state = new_state; // remember new state + if (new_state == LS_UP) + ed_link_up(new_speed); + else if (new_state == LS_DOWN) + ed_link_down(); + } + else if (new_state == LS_UP && new_speed != ed_state.link_speed){ + ed_state.link_speed = new_speed; // remember new speed + ed_link_speed_change(new_speed); + } +} + +/* + * This is fired when the ethernet PHY state changes + */ +static void +eth_phy_irq_handler(unsigned irq) +{ + ed_check_phy_state(); + eth_mac_miim_read(PHY_INT_STATUS); +// eth_mac_miim_write(PHY_INT_CLEAR, ~0); // clear all ints +} + +void +ethernet_init(void) +{ + eth_mac_init(ethernet_mac_addr()); + + ed_state.link_state = LS_UNKNOWN; + ed_state.link_speed = S_UNKNOWN; + + // initialize MAC registers + // eth_mac->tx_hwmark = 0x1e; + //eth_mac->tx_lwmark = 0x19; + + //eth_mac->crc_chk_en = 1; + //eth_mac->rx_max_length = 2048; + + // configure PAUSE frame stuff + //eth_mac->tx_pause_en = 1; // pay attn to pause frames sent to us + + //eth_mac->pause_quanta_set = 38; // a bit more than 1 max frame 16kb/512 + fudge + //eth_mac->pause_frame_send_en = 1; // enable sending pause frames + + + // setup PHY to interrupt on changes + + unsigned mask = + (PHY_INT_ENABLE //master interrupt enable + | PHY_INT_LINK_STATUS_CHANGE + | PHY_INT_RX_STATUS_CHANGE + ); + + eth_mac_miim_read(PHY_INT_STATUS); + eth_mac_miim_write(PHY_INT_MASK, mask); // enable the ones we want + + pic_register_handler(IRQ_PHY, eth_phy_irq_handler); + + // Advertise our flow control configuation. + // + // We and the link partner each specify two bits in the base page + // related to autoconfiguration: NWAY_AR_PAUSE and NWAY_AR_ASM_DIR. + // The bits say what a device is "willing" to do, not what may actually + // happen as a result of the negotiation. There are 4 cases: + // + // PAUSE ASM_DIR + // + // 0 0 I have no flow control capability. + // + // 1 0 I both assert and respond to flow control. + // + // 0 1 I assert flow control, but cannot respond. That is, + // I want to be able to send PAUSE frames, but will ignore any + // you send to me. (This is our configuration.) + // + // 1 1 I can both assert and respond to flow control AND I am willing + // to operate symmetrically OR asymmetrically in EITHER direction. + // (We hope the link partner advertises this, otherwise we don't + // get what we want.) + + int t = eth_mac_miim_read(PHY_AUTONEG_ADV); + t &= ~(NWAY_AR_PAUSE | NWAY_AR_ASM_DIR); + t |= NWAY_AR_ASM_DIR; + + // Say we can't to 10BASE-T or 100BASE-TX, half or full duplex + t &= ~(NWAY_AR_10T_HD_CAPS | NWAY_AR_10T_FD_CAPS | NWAY_AR_100TX_HD_CAPS | NWAY_AR_100TX_FD_CAPS); + + eth_mac_miim_write(PHY_AUTONEG_ADV, t); + int r = eth_mac_miim_read(PHY_AUTONEG_ADV); // DEBUG, read back + if (t != r){ + printf("PHY_AUTONEG_ADV: wrote 0x%x, got 0x%x\n", t, r); + } + + // Restart autonegotation. + // We want to ensure that we're advertising our PAUSE capabilities. + t = eth_mac_miim_read(PHY_CTRL); + eth_mac_miim_write(PHY_CTRL, t | MII_CR_RESTART_AUTO_NEG); +} + +static bool +unprogrammed(const void *t, size_t len) +{ + int i; + uint8_t *p = (uint8_t *)t; + bool all_zeros = true; + bool all_ones = true; + for (i = 0; i < len; i++){ + all_zeros &= p[i] == 0x00; + all_ones &= p[i] == 0xff; + } + return all_ones | all_zeros; +} + +//////////////////// MAC Addr Stuff /////////////////////// + +static int8_t src_mac_addr_initialized = false; +static eth_mac_addr_t src_mac_addr = {{ + 0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff + }}; + +const eth_mac_addr_t * +ethernet_mac_addr(void) +{ + if (!src_mac_addr_initialized){ // fetch from eeprom + src_mac_addr_initialized = true; + + // if we're simulating, don't read the EEPROM model, it's REALLY slow + if (hwconfig_simulation_p()) + return &src_mac_addr; + + eth_mac_addr_t tmp; + bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, &tmp, sizeof(tmp)); + if (!ok || unprogrammed(&tmp, sizeof(tmp))){ + // use the default + } + else + src_mac_addr = tmp; + } + + return &src_mac_addr; +} + +bool +ethernet_set_mac_addr(const eth_mac_addr_t *t) +{ + bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_MAC_ADDR, t, sizeof(eth_mac_addr_t)); + if (ok){ + src_mac_addr = *t; + src_mac_addr_initialized = true; + //eth_mac_set_addr(t); //this breaks the link + } + + return ok; +} + +//////////////////// IP Addr Stuff /////////////////////// + +static int8_t src_ip_addr_initialized = false; +static struct ip_addr src_ip_addr = { + (192 << 24 | 168 << 16 | 10 << 8 | 2 << 0) +}; + + +const struct ip_addr *get_ip_addr(void) +{ + if (!src_ip_addr_initialized){ // fetch from eeprom + src_ip_addr_initialized = true; + + // if we're simulating, don't read the EEPROM model, it's REALLY slow + if (hwconfig_simulation_p()) + return &src_ip_addr; + + struct ip_addr tmp; + bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, &tmp, sizeof(tmp)); + if (!ok || unprogrammed(&tmp, sizeof(tmp))){ + // use the default + } + else + src_ip_addr = tmp; + } + + return &src_ip_addr; +} + +bool set_ip_addr(const struct ip_addr *t){ + bool ok = eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, t, sizeof(struct ip_addr)); + if (ok){ + src_ip_addr = *t; + src_ip_addr_initialized = true; + } + + return ok; +} + +int +ethernet_check_errors(void) +{ + // these registers are reset when read + + int r = 0; + /* + if (eth_mac_read_rmon(0x05) != 0) + r |= RME_RX_CRC; + if (eth_mac_read_rmon(0x06) != 0) + r |= RME_RX_FIFO_FULL; + if (eth_mac_read_rmon(0x07) != 0) + r |= RME_RX_2SHORT_2LONG; + + if (eth_mac_read_rmon(0x25) != 0) + r |= RME_TX_JAM_DROP; + if (eth_mac_read_rmon(0x26) != 0) + r |= RME_TX_FIFO_UNDER; + if (eth_mac_read_rmon(0x27) != 0) + r |= RME_TX_FIFO_OVER; + */ + return r; +} -- cgit v1.2.3 From 9b63845669056ace2ca50a2c406ce6cf3657ec74 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 27 Jul 2010 20:11:05 -0700 Subject: Ethernet mods for activity LED. --- firmware/microblaze/lib/eth_mac.c | 2 +- firmware/microblaze/lib/pic.c | 2 +- firmware/microblaze/usrp2p/eth_phy.h | 25 +++++++++++++++++++++++++ firmware/microblaze/usrp2p/ethernet.c | 8 ++++++-- 4 files changed, 33 insertions(+), 4 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/eth_mac.c b/firmware/microblaze/lib/eth_mac.c index cd0179deb..034a4d494 100644 --- a/firmware/microblaze/lib/eth_mac.c +++ b/firmware/microblaze/lib/eth_mac.c @@ -104,7 +104,7 @@ eth_mac_miim_write(int addr, int value) eth_mac->miitx_data = value; eth_mac->miicommand = MIIC_WCTRLDATA; - //printf("MIIM-WRITE ADDR 0x%x VAL 0x%x\n",addr,value); +// printf("MIIM-WRITE ADDR 0x%x VAL 0x%x\n",addr,value); while((eth_mac->miistatus & MIIS_BUSY) != 0) ; } diff --git a/firmware/microblaze/lib/pic.c b/firmware/microblaze/lib/pic.c index 4575bd775..e89d2b755 100644 --- a/firmware/microblaze/lib/pic.c +++ b/firmware/microblaze/lib/pic.c @@ -44,7 +44,7 @@ pic_init(void) // uP is level triggered pic_regs->mask = ~0; // mask all interrupts - pic_regs->edge_enable = PIC_ONETIME_INT | PIC_PHY_INT; + pic_regs->edge_enable = PIC_ONETIME_INT; pic_regs->polarity = ~0 & ~PIC_PHY_INT; // rising edge pic_regs->pending = ~0; // clear all pending ints } diff --git a/firmware/microblaze/usrp2p/eth_phy.h b/firmware/microblaze/usrp2p/eth_phy.h index 9328debee..d233e96e8 100644 --- a/firmware/microblaze/usrp2p/eth_phy.h +++ b/firmware/microblaze/usrp2p/eth_phy.h @@ -42,6 +42,7 @@ #define PHY_INT_MASK 24 #define PHY_INT_STATUS 25 #define PHY_PHY_STATUS 26 +#define PHY_LED2 28 /* Bit definitions for some of the registers above */ @@ -207,4 +208,28 @@ #define PHY_INT_MDIO_SYNC_LOST (1 << 9) #define PHY_INT_TDR_IP_PHONE (1 << 10) +/* PHY LED status register 2 (used for controlling link LED for activity light) */ +#define PHY_LED_TXRX_LSB 12 +#define PHY_LED_LINK_LSB 8 +#define PHY_LED_100_LSB 4 +#define PHY_LED_1000_LSB 0 + +#define LED_1000 0 +#define LED_100_TX 1 +#define LED_10 2 +#define LED_1000_ON_100_BLINK 3 +#define LED_LINK 4 +#define LED_TX 5 +#define LED_RX 6 +#define LED_ACTIVITY 7 +#define LED_FULLDUPLEX 8 +#define LED_COLLISION 9 +#define LED_LINK_ON_ACTIVITY_BLINK 10 +#define LED_LINK_ON_RX_BLINK 11 +#define LED_FULL_DUPLEX_ON_COLLISION_BLINK 12 +#define LED_BLINK 13 +#define LED_ON 14 +#define LED_OFF 15 + + #endif /* INCLUDED_ETH_PHY_H */ diff --git a/firmware/microblaze/usrp2p/ethernet.c b/firmware/microblaze/usrp2p/ethernet.c index 134650326..07224d3b7 100644 --- a/firmware/microblaze/usrp2p/ethernet.c +++ b/firmware/microblaze/usrp2p/ethernet.c @@ -29,7 +29,7 @@ #include #include "usrp2/fw_common.h" -#define VERBOSE 1 +#define VERBOSE 0 static ethernet_t ed_state; static ethernet_link_changed_callback_t ed_callback = 0; @@ -222,9 +222,13 @@ ethernet_init(void) | PHY_INT_RX_STATUS_CHANGE ); - eth_mac_miim_read(PHY_INT_STATUS); + eth_mac_miim_read(PHY_INT_STATUS); //clear interrupts eth_mac_miim_write(PHY_INT_MASK, mask); // enable the ones we want + //set the LED behavior to activity instead of link + unsigned led = (LED_ACTIVITY << PHY_LED_LINK_LSB); + eth_mac_miim_write(PHY_LED2, led); + pic_register_handler(IRQ_PHY, eth_phy_irq_handler); // Advertise our flow control configuation. -- cgit v1.2.3 From fd3a2ac058de6bdd69b9f388658e4189a9c5b32d Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 28 Jul 2010 09:54:56 -0700 Subject: Ethernet blinky light changes. Link LED works. D201 (next to PHY) blinks on TX. Yellow LED on connector blinks on TX/RX. --- firmware/microblaze/usrp2p/ethernet.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'firmware') diff --git a/firmware/microblaze/usrp2p/ethernet.c b/firmware/microblaze/usrp2p/ethernet.c index 07224d3b7..80c303153 100644 --- a/firmware/microblaze/usrp2p/ethernet.c +++ b/firmware/microblaze/usrp2p/ethernet.c @@ -69,6 +69,10 @@ ed_link_up(int speed) ed_set_mac_speed(speed); + //turn on link LED for USRP2P + hal_set_leds((1 << 0), (1 << 0)); + + if (ed_callback) // fire link changed callback (*ed_callback)(speed); } @@ -78,6 +82,9 @@ ed_link_down(void) { // putstr("ed_link_down\n"); + //turn off link LED for USRP2P + hal_set_leds(0, (1 << 0)); + if (ed_callback) // fire link changed callback (*ed_callback)(0); } @@ -226,7 +233,7 @@ ethernet_init(void) eth_mac_miim_write(PHY_INT_MASK, mask); // enable the ones we want //set the LED behavior to activity instead of link - unsigned led = (LED_ACTIVITY << PHY_LED_LINK_LSB); + unsigned led = (LED_ACTIVITY << PHY_LED_LINK_LSB) | (LED_TX << PHY_LED_TXRX_LSB); eth_mac_miim_write(PHY_LED2, led); pic_register_handler(IRQ_PHY, eth_phy_irq_handler); -- cgit v1.2.3 From b82b3f7a6ff2302b357397e8b72d43aff5644896 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 28 Jul 2010 14:48:45 -0700 Subject: Widened SPI slave select bus to 16 bits in host and firmware. --- firmware/microblaze/lib/spi.c | 2 +- host/lib/usrp/usrp2/fw_common.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/spi.c b/firmware/microblaze/lib/spi.c index 937397df6..bef808e57 100644 --- a/firmware/microblaze/lib/spi.c +++ b/firmware/microblaze/lib/spi.c @@ -43,7 +43,7 @@ spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags spi_wait(); // Tell it which SPI slave device to access - spi_regs->ss = slave & 0xff; + spi_regs->ss = slave & 0xffff; // Data we will send spi_regs->txrx0 = data; diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index c4dabf5bc..389ac9892 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -104,12 +104,12 @@ typedef struct{ union{ __stdint(uint32_t) ip_addr; struct { - __stdint(uint8_t) dev; + __stdint(uint32_t) dev; + __stdint(uint32_t) data; __stdint(uint8_t) miso_edge; __stdint(uint8_t) mosi_edge; - __stdint(uint8_t) readback; - __stdint(uint32_t) data; __stdint(uint8_t) num_bits; + __stdint(uint8_t) readback; } spi_args; struct { __stdint(uint8_t) addr; -- cgit v1.2.3 From 329415df45212206c44c9ae44851f972dce3ed53 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 28 Jul 2010 16:48:45 -0700 Subject: Stripped out all the clock functionality except for init'ing the FPGA. Clock smarts have been host-side for a while, so this is redundant code. --- firmware/microblaze/lib/Makefile.inc | 1 + firmware/microblaze/lib/clocks.c | 261 +++++++++++++++++++++++++++++++++ firmware/microblaze/lib/clocks.h | 8 +- firmware/microblaze/usrp2/Makefile.am | 1 - firmware/microblaze/usrp2/clocks.c | 239 ------------------------------ firmware/microblaze/usrp2p/Makefile.am | 1 - firmware/microblaze/usrp2p/clocks.c | 259 -------------------------------- 7 files changed, 266 insertions(+), 504 deletions(-) create mode 100644 firmware/microblaze/lib/clocks.c delete mode 100644 firmware/microblaze/usrp2/clocks.c delete mode 100644 firmware/microblaze/usrp2p/clocks.c (limited to 'firmware') diff --git a/firmware/microblaze/lib/Makefile.inc b/firmware/microblaze/lib/Makefile.inc index 02a267d35..ae123f531 100644 --- a/firmware/microblaze/lib/Makefile.inc +++ b/firmware/microblaze/lib/Makefile.inc @@ -23,6 +23,7 @@ COMMON_SRCS = \ $(top_srcdir)/lib/ad9510.c \ $(top_srcdir)/lib/bsm12.c \ $(top_srcdir)/lib/buffer_pool.c \ + $(top_srcdir)/lib/clocks.c \ $(top_srcdir)/lib/dbsm.c \ $(top_srcdir)/lib/eeprom.c \ $(top_srcdir)/lib/eth_mac.c \ diff --git a/firmware/microblaze/lib/clocks.c b/firmware/microblaze/lib/clocks.c new file mode 100644 index 000000000..08f15deb1 --- /dev/null +++ b/firmware/microblaze/lib/clocks.c @@ -0,0 +1,261 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +#include "memory_map.h" +#include "ad9510.h" +#include "spi.h" +#include "u2_init.h" +#include "nonstdio.h" + +//USRP2PLUS clocks: +//Clock 0: testclk +//Clock 1: FPGA clk +//Clock 2: ADC clk +//Clock 3: DAC clk +//Clock 4: SER clk +//Clock 5: TX dboard clk +//Clock 6: EXP clk +//Clock 7: RX dboard clk + +//TODO: should have enough brains to init the FPGA clock for USRP2+. all others are suspect. +//note that without EEPROM support u2_hw_rev_major is going to be incorrect. + +void +clocks_init(void) +{ + // Set up basic clocking functions in AD9510 + ad9510_write_reg(0x45, 0x01); // CLK2 drives distribution + + clocks_enable_fpga_clk(true, 1); + + spi_wait(); + + // Set up PLL for 10 MHz reference + // Reg 4, A counter, Don't Care +// ad9510_write_reg(0x05, 0x00); // Reg 5, B counter MSBs, 0 +// ad9510_write_reg(0x06, 0x05); // Reg 6, B counter LSBs, 5 + // Reg 7, Loss of reference detect, doesn't work yet, 0 +// ad9510_write_reg(0x5A, 0x01); // Update Regs + + // Primary clock configuration +// clocks_mimo_config(MC_WE_DONT_LOCK); + + // Set up other clocks + //clocks_enable_test_clk(false, 0); + //clocks_enable_tx_dboard(false, 0); + //clocks_enable_rx_dboard(false, 0); +// clocks_enable_eth_phyclk(false, 0); //PHY clk is separate now (u2r4, u2p) + + // Enable clock to ADCs and DACs + //clocks_enable_dac_clk(true, 1); + //clocks_enable_adc_clk(true, 1); +} + +/* +void +clocks_mimo_config(int flags) +{ + if (flags & _MC_WE_LOCK){ + // Reg 8, Charge pump on, dig lock det, positive PFD, 47 + ad9510_write_reg(0x08, 0x47); + } + else { + // Reg 8, Charge pump off, dig lock det, positive PFD + ad9510_write_reg(0x08, 0x00); + } + + // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA + ad9510_write_reg(0x09, 0x00); + // Reg A, Prescaler of 2, everything normal 04 + ad9510_write_reg(0x0A, 0x04); + // Reg B, R Div MSBs, 0 + ad9510_write_reg(0x0B, 0x00); + // Reg C, R Div LSBs, 1 + ad9510_write_reg(0x0C, 0x01); + // Reg D, Antibacklash, Digital lock det, 0 + + ad9510_write_reg(0x5A, 0x01); // Update Regs + + spi_wait(); + + // Allow for clock switchover + + if (flags & _MC_WE_LOCK){ // WE LOCK + if (flags & _MC_MIMO_CLK_INPUT) { + // Turn on ref output and choose the MIMO connector + output_regs->clk_ctrl = 0x15; + } + else { + // turn on ref output and choose the SMA + output_regs->clk_ctrl = 0x1C; + } + } + else { // WE DONT LOCK + // Disable both ext clk inputs + output_regs->clk_ctrl = 0x10; + } + + // Do we drive a clock onto the MIMO connector? + if (flags & MC_PROVIDE_CLK_TO_MIMO) + clocks_enable_clkexp_out(true,10); + else + clocks_enable_clkexp_out(false,0); +} +*/ +/* +bool +clocks_lock_detect() +{ + if(pic_regs->pending & PIC_CLKSTATUS) + return true; + return false; +} +*/ +int inline +clocks_gen_div(int divisor) +{ + int L,H; + L = (divisor>>1)-1; + H = divisor-L-2; + return (L<<4)|H; +} + +#define CLOCK_OUT_EN 0x08 +#define CLOCK_OUT_DIS_CMOS 0x01 +#define CLOCK_OUT_DIS_PECL 0x02 +#define CLOCK_DIV_DIS 0x80 +#define CLOCK_DIV_EN 0x00 + +#define CLOCK_MODE_PECL 1 +#define CLOCK_MODE_LVDS 2 +#define CLOCK_MODE_CMOS 3 + +//CHANGED: set to PECL for default behavior +void +clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mode) +{ + int enable_word, div_word, div_en_word; + + switch(mode) { + case CLOCK_MODE_LVDS : + enable_word = enable ? 0x02 : 0x03; + break; + case CLOCK_MODE_CMOS : + enable_word = enable ? 0x08 : 0x09; + break; + case CLOCK_MODE_PECL : + default: + enable_word = enable ? 0x08 : 0x0A; + break; + } + if(enable && (divisor>1)) { + div_word = clocks_gen_div(divisor); + div_en_word = CLOCK_DIV_EN; + } + else { + div_word = 0; + div_en_word = CLOCK_DIV_DIS; + } + + ad9510_write_reg(reg_en,enable_word); // Output en/dis + ad9510_write_reg(reg_div,div_word); // Set divisor + ad9510_write_reg(reg_div+1,div_en_word); // Enable or Bypass Divider + ad9510_write_reg(0x5A, 0x01); // Update Regs +} + +// Clock 0 +/*void +clocks_enable_test_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL); +}*/ + +// Clock 1 +void +clocks_enable_fpga_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL); +} +/* +// Clock 2 on Rev 3, Clock 5 on Rev 4, Clock 6 on USRP2+ +void +clocks_enable_clkexp_out(bool enable, int divisor) +{ + if(u2_hw_rev_major == 3) + clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); + else if(u2_hw_rev_major == 4) { + ad9510_write_reg(0x34,0x00); // Turn on fine delay + ad9510_write_reg(0x35,0x00); // Set Full Scale to nearly 10ns + ad9510_write_reg(0x36,0x1c); // Set fine delay. 0x20 is midscale + clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); + } + else if(u2_hw_rev_major == 10) { + ad9510_write_reg(0x34, 0x00); + ad9510_write_reg(0x35, 0x00); + ad9510_write_reg(0x36, 0x1C); + clocks_enable_XXX_clk(enable, divisor, 0x42, 0x52, CLOCK_MODE_LVDS); + } + else + putstr("ERR (clocks_enable_clkexp_out): Invalid hw rev, don't know what to do!\n"); +} +*/ +/* +// Clock 5 on Rev 3, none (was 2) on Rev 4, none on USRP2+ +void +clocks_enable_eth_phyclk(bool enable, int divisor) +{ + if(u2_hw_rev_major == 3) + clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); + else if(u2_hw_rev_major == 4) + clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); + else + putstr("(clocks_enable_eth_phyclk): no eth PHY clock or invalid hw rev\n"); //not really an error +} +*/ +// Clock 3 +/*void +clocks_enable_dac_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL); +}*/ + +// Clock 4 +/*void +clocks_enable_adc_clk(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS); +}*/ + +// Clock 6 +/*void +clocks_enable_tx_dboard(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS); +}*/ + +// Clock 7 +/*void +clocks_enable_rx_dboard(bool enable, int divisor) +{ + clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS); +}*/ diff --git a/firmware/microblaze/lib/clocks.h b/firmware/microblaze/lib/clocks.h index a285e03dd..2769fd434 100644 --- a/firmware/microblaze/lib/clocks.h +++ b/firmware/microblaze/lib/clocks.h @@ -43,12 +43,12 @@ void clocks_init(void); * Configure our master clock source, and whether or not we drive a * clock onto the mimo connector. See MC_flags in usrp2_mimo_config.h. */ -void clocks_mimo_config(int flags); +//void clocks_mimo_config(int flags); /*! * \brief Lock Detect -- Return True if our PLL is locked */ -bool clocks_lock_detect(); +//bool clocks_lock_detect(); /*! * \brief Enable or disable test clock (extra clock signal) @@ -63,12 +63,12 @@ void clocks_enable_fpga_clk(bool enable, int divisor); /*! * \brief Enable or disable clock output sent to MIMO connector */ -void clocks_enable_clkexp_out(bool enable, int divisor); +//void clocks_enable_clkexp_out(bool enable, int divisor); /*! * \brief Enable or disable ethernet phyclk, should always be disabled */ -void clocks_enable_eth_phyclk(bool enable, int divisor); +//void clocks_enable_eth_phyclk(bool enable, int divisor); /*! * \brief Enable or disable clock to DAC diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am index b45d2481b..8da013980 100644 --- a/firmware/microblaze/usrp2/Makefile.am +++ b/firmware/microblaze/usrp2/Makefile.am @@ -33,7 +33,6 @@ noinst_LIBRARIES = libusrp2.a libusrp2_a_SOURCES = \ $(COMMON_SRCS) \ - clocks.c \ sd.c \ ethernet.c diff --git a/firmware/microblaze/usrp2/clocks.c b/firmware/microblaze/usrp2/clocks.c deleted file mode 100644 index ccc4a7cc7..000000000 --- a/firmware/microblaze/usrp2/clocks.c +++ /dev/null @@ -1,239 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include - -#include "memory_map.h" -#include "ad9510.h" -#include "spi.h" -#include "u2_init.h" -#include "nonstdio.h" - -void -clocks_init(void) -{ - // Set up basic clocking functions in AD9510 - ad9510_write_reg(0x45, 0x00); // CLK2 drives distribution - - clocks_enable_fpga_clk(true, 1); - - spi_wait(); - - // Set up PLL for 10 MHz reference - // Reg 4, A counter, Don't Care - ad9510_write_reg(0x05, 0x00); // Reg 5, B counter MSBs, 0 - ad9510_write_reg(0x06, 0x05); // Reg 6, B counter LSBs, 5 - // Reg 7, Loss of reference detect, doesn't work yet, 0 - ad9510_write_reg(0x5A, 0x01); // Update Regs - - // Primary clock configuration - clocks_mimo_config(MC_WE_DONT_LOCK); - - // Set up other clocks - //clocks_enable_test_clk(false, 0); - //clocks_enable_tx_dboard(false, 0); - //clocks_enable_rx_dboard(false, 0); - clocks_enable_eth_phyclk(false, 0); - - // Enable clock to ADCs and DACs - //clocks_enable_dac_clk(true, 1); - //clocks_enable_adc_clk(true, 1); -} - - -void -clocks_mimo_config(int flags) -{ - if (flags & _MC_WE_LOCK){ - // Reg 8, Charge pump on, dig lock det, positive PFD, 47 - ad9510_write_reg(0x08, 0x47); - } - else { - // Reg 8, Charge pump off, dig lock det, positive PFD - ad9510_write_reg(0x08, 0x00); - } - - // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA - ad9510_write_reg(0x09, 0x00); - // Reg A, Prescaler of 2, everything normal 04 - ad9510_write_reg(0x0A, 0x04); - // Reg B, R Div MSBs, 0 - ad9510_write_reg(0x0B, 0x00); - // Reg C, R Div LSBs, 1 - ad9510_write_reg(0x0C, 0x01); - // Reg D, Antibacklash, Digital lock det, 0 - - ad9510_write_reg(0x5A, 0x01); // Update Regs - - spi_wait(); - - // Allow for clock switchover - - if (flags & _MC_WE_LOCK){ // WE LOCK - if (flags & _MC_MIMO_CLK_INPUT) { - // Turn on ref output and choose the MIMO connector - output_regs->clk_ctrl = 0x15; - } - else { - // turn on ref output and choose the SMA - output_regs->clk_ctrl = 0x1C; - } - } - else { // WE DONT LOCK - // Disable both ext clk inputs - output_regs->clk_ctrl = 0x10; - } - - // Do we drive a clock onto the MIMO connector? - if (flags & MC_PROVIDE_CLK_TO_MIMO) - clocks_enable_clkexp_out(true,10); - else - clocks_enable_clkexp_out(false,0); -} - -bool -clocks_lock_detect() -{ - if(pic_regs->pending & PIC_CLKSTATUS) - return true; - return false; -} - -int inline -clocks_gen_div(int divisor) -{ - int L,H; - L = (divisor>>1)-1; - H = divisor-L-2; - return (L<<4)|H; -} - -#define CLOCK_OUT_EN 0x08 -#define CLOCK_OUT_DIS_CMOS 0x01 -#define CLOCK_OUT_DIS_PECL 0x02 -#define CLOCK_DIV_DIS 0x80 -#define CLOCK_DIV_EN 0x00 - -#define CLOCK_MODE_PECL 1 -#define CLOCK_MODE_LVDS 2 -#define CLOCK_MODE_CMOS 3 - -void -clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mode) -{ - int enable_word, div_word, div_en_word; - - switch(mode) { - case CLOCK_MODE_PECL : - enable_word = enable ? 0x08 : 0x0A; - break; - case CLOCK_MODE_LVDS : - enable_word = enable ? 0x02 : 0x03; - break; - case CLOCK_MODE_CMOS : - enable_word = enable ? 0x08 : 0x09; - break; - } - if(enable && (divisor>1)) { - div_word = clocks_gen_div(divisor); - div_en_word = CLOCK_DIV_EN; - } - else { - div_word = 0; - div_en_word = CLOCK_DIV_DIS; - } - - ad9510_write_reg(reg_en,enable_word); // Output en/dis - ad9510_write_reg(reg_div,div_word); // Set divisor - ad9510_write_reg(reg_div+1,div_en_word); // Enable or Bypass Divider - ad9510_write_reg(0x5A, 0x01); // Update Regs -} - -// Clock 0 -/*void -clocks_enable_test_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL); -}*/ - -// Clock 1 -void -clocks_enable_fpga_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL); -} - -// Clock 2 on Rev 3, Clock 5 on Rev 4 -void -clocks_enable_clkexp_out(bool enable, int divisor) -{ - if(u2_hw_rev_major == 3) - clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); - else if(u2_hw_rev_major == 4) { - ad9510_write_reg(0x34,0x00); // Turn on fine delay - ad9510_write_reg(0x35,0x00); // Set Full Scale to nearly 10ns - ad9510_write_reg(0x36,0x1c); // Set fine delay. 0x20 is midscale - clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); - - } - else - putstr("ERR: Invalid Rev\n"); -} - -// Clock 5 on Rev 3, none (was 2) on Rev 4 -void -clocks_enable_eth_phyclk(bool enable, int divisor) -{ - if(u2_hw_rev_major == 3) - clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); - else if(u2_hw_rev_major == 4) - clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); - else - putstr("ERR: Invalid Rev\n"); -} - -// Clock 3 -/*void -clocks_enable_dac_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL); -}*/ - -// Clock 4 -/*void -clocks_enable_adc_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS); -}*/ - -// Clock 6 -/*void -clocks_enable_tx_dboard(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS); -}*/ - -// Clock 7 -/*void -clocks_enable_rx_dboard(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS); -}*/ diff --git a/firmware/microblaze/usrp2p/Makefile.am b/firmware/microblaze/usrp2p/Makefile.am index 86affc1f3..ddc7006ca 100644 --- a/firmware/microblaze/usrp2p/Makefile.am +++ b/firmware/microblaze/usrp2p/Makefile.am @@ -45,7 +45,6 @@ noinst_LIBRARIES = libusrp2p.a libusrp2p_a_SOURCES = \ $(COMMON_SRCS) \ - clocks.c \ spif.c \ spi_flash.c \ spi_flash_read.c \ diff --git a/firmware/microblaze/usrp2p/clocks.c b/firmware/microblaze/usrp2p/clocks.c deleted file mode 100644 index 3488ec468..000000000 --- a/firmware/microblaze/usrp2p/clocks.c +++ /dev/null @@ -1,259 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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, see . - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include - -#include "memory_map.h" -#include "ad9510.h" -#include "spi.h" -#include "u2_init.h" -#include "nonstdio.h" - -//USRP2PLUS clocks: -//Clock 0: testclk -//Clock 1: FPGA clk -//Clock 2: ADC clk -//Clock 3: DAC clk -//Clock 4: SER clk -//Clock 5: TX dboard clk -//Clock 6: EXP clk -//Clock 7: RX dboard clk - -//TODO: should have enough brains to init the FPGA clock for USRP2+. all others are suspect. -//note that without EEPROM support u2_hw_rev_major is going to be incorrect. - -void -clocks_init(void) -{ - // Set up basic clocking functions in AD9510 - ad9510_write_reg(0x45, 0x01); // CLK2 drives distribution - - clocks_enable_fpga_clk(true, 1); - - spi_wait(); - - // Set up PLL for 10 MHz reference - // Reg 4, A counter, Don't Care - ad9510_write_reg(0x05, 0x00); // Reg 5, B counter MSBs, 0 - ad9510_write_reg(0x06, 0x05); // Reg 6, B counter LSBs, 5 - // Reg 7, Loss of reference detect, doesn't work yet, 0 - ad9510_write_reg(0x5A, 0x01); // Update Regs - - // Primary clock configuration - clocks_mimo_config(MC_WE_DONT_LOCK); - - // Set up other clocks - //clocks_enable_test_clk(false, 0); - //clocks_enable_tx_dboard(false, 0); - //clocks_enable_rx_dboard(false, 0); - clocks_enable_eth_phyclk(false, 0); //PHY clk is separate now (u2r4, u2p) - - // Enable clock to ADCs and DACs - //clocks_enable_dac_clk(true, 1); - //clocks_enable_adc_clk(true, 1); -} - - -void -clocks_mimo_config(int flags) -{ - if (flags & _MC_WE_LOCK){ - // Reg 8, Charge pump on, dig lock det, positive PFD, 47 - ad9510_write_reg(0x08, 0x47); - } - else { - // Reg 8, Charge pump off, dig lock det, positive PFD - ad9510_write_reg(0x08, 0x00); - } - - // Reg 9, Charge pump current, 0x40=3mA, 0x00=650uA - ad9510_write_reg(0x09, 0x00); - // Reg A, Prescaler of 2, everything normal 04 - ad9510_write_reg(0x0A, 0x04); - // Reg B, R Div MSBs, 0 - ad9510_write_reg(0x0B, 0x00); - // Reg C, R Div LSBs, 1 - ad9510_write_reg(0x0C, 0x01); - // Reg D, Antibacklash, Digital lock det, 0 - - ad9510_write_reg(0x5A, 0x01); // Update Regs - - spi_wait(); - - // Allow for clock switchover - - if (flags & _MC_WE_LOCK){ // WE LOCK - if (flags & _MC_MIMO_CLK_INPUT) { - // Turn on ref output and choose the MIMO connector - output_regs->clk_ctrl = 0x15; - } - else { - // turn on ref output and choose the SMA - output_regs->clk_ctrl = 0x1C; - } - } - else { // WE DONT LOCK - // Disable both ext clk inputs - output_regs->clk_ctrl = 0x10; - } - - // Do we drive a clock onto the MIMO connector? - if (flags & MC_PROVIDE_CLK_TO_MIMO) - clocks_enable_clkexp_out(true,10); - else - clocks_enable_clkexp_out(false,0); -} - -bool -clocks_lock_detect() -{ - if(pic_regs->pending & PIC_CLKSTATUS) - return true; - return false; -} - -int inline -clocks_gen_div(int divisor) -{ - int L,H; - L = (divisor>>1)-1; - H = divisor-L-2; - return (L<<4)|H; -} - -#define CLOCK_OUT_EN 0x08 -#define CLOCK_OUT_DIS_CMOS 0x01 -#define CLOCK_OUT_DIS_PECL 0x02 -#define CLOCK_DIV_DIS 0x80 -#define CLOCK_DIV_EN 0x00 - -#define CLOCK_MODE_PECL 1 -#define CLOCK_MODE_LVDS 2 -#define CLOCK_MODE_CMOS 3 - -//CHANGED: set to PECL for default behavior -void -clocks_enable_XXX_clk(bool enable, int divisor, int reg_en, int reg_div, int mode) -{ - int enable_word, div_word, div_en_word; - - switch(mode) { - case CLOCK_MODE_LVDS : - enable_word = enable ? 0x02 : 0x03; - break; - case CLOCK_MODE_CMOS : - enable_word = enable ? 0x08 : 0x09; - break; - case CLOCK_MODE_PECL : - default: - enable_word = enable ? 0x08 : 0x0A; - break; - } - if(enable && (divisor>1)) { - div_word = clocks_gen_div(divisor); - div_en_word = CLOCK_DIV_EN; - } - else { - div_word = 0; - div_en_word = CLOCK_DIV_DIS; - } - - ad9510_write_reg(reg_en,enable_word); // Output en/dis - ad9510_write_reg(reg_div,div_word); // Set divisor - ad9510_write_reg(reg_div+1,div_en_word); // Enable or Bypass Divider - ad9510_write_reg(0x5A, 0x01); // Update Regs -} - -// Clock 0 -/*void -clocks_enable_test_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3C,0x48,CLOCK_MODE_PECL); -}*/ - -// Clock 1 -void -clocks_enable_fpga_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3D,0x4A,CLOCK_MODE_PECL); -} - -// Clock 2 on Rev 3, Clock 5 on Rev 4, Clock 6 on USRP2+ -void -clocks_enable_clkexp_out(bool enable, int divisor) -{ - if(u2_hw_rev_major == 3) - clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); - else if(u2_hw_rev_major == 4) { - ad9510_write_reg(0x34,0x00); // Turn on fine delay - ad9510_write_reg(0x35,0x00); // Set Full Scale to nearly 10ns - ad9510_write_reg(0x36,0x1c); // Set fine delay. 0x20 is midscale - clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); - } - else if(u2_hw_rev_major == 10) { - ad9510_write_reg(0x34, 0x00); - ad9510_write_reg(0x35, 0x00); - ad9510_write_reg(0x36, 0x1C); - clocks_enable_XXX_clk(enable, divisor, 0x42, 0x52, CLOCK_MODE_LVDS); - } - else - putstr("ERR (clocks_enable_clkexp_out): Invalid hw rev, don't know what to do!\n"); -} - -// Clock 5 on Rev 3, none (was 2) on Rev 4, none on USRP2+ -void -clocks_enable_eth_phyclk(bool enable, int divisor) -{ - if(u2_hw_rev_major == 3) - clocks_enable_XXX_clk(enable,divisor,0x41,0x52,CLOCK_MODE_LVDS); - else if(u2_hw_rev_major == 4) - clocks_enable_XXX_clk(enable,divisor,0x3E,0x4C,CLOCK_MODE_PECL); - else - putstr("(clocks_enable_eth_phyclk): no eth PHY clock or invalid hw rev\n"); //not really an error -} - -// Clock 3 -/*void -clocks_enable_dac_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x3F,0x4E,CLOCK_MODE_PECL); -}*/ - -// Clock 4 -/*void -clocks_enable_adc_clk(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x40,0x50,CLOCK_MODE_LVDS); -}*/ - -// Clock 6 -/*void -clocks_enable_tx_dboard(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x42,0x54,CLOCK_MODE_CMOS); -}*/ - -// Clock 7 -/*void -clocks_enable_rx_dboard(bool enable, int divisor) -{ - clocks_enable_XXX_clk(enable,divisor,0x43,0x56,CLOCK_MODE_CMOS); -}*/ -- cgit v1.2.3 From f9cec099f9909bbdf7b9f1c20db9c81173a9b98d Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 28 Jul 2010 18:22:32 -0700 Subject: Added back in clock_mimo_enable stuff since USRP2 breaks without it. Should look further into initializing ALL clocks on host side. --- firmware/microblaze/lib/clocks.c | 14 +++++++------- firmware/microblaze/lib/clocks.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/clocks.c b/firmware/microblaze/lib/clocks.c index 08f15deb1..b9bd2e107 100644 --- a/firmware/microblaze/lib/clocks.c +++ b/firmware/microblaze/lib/clocks.c @@ -58,7 +58,7 @@ clocks_init(void) // ad9510_write_reg(0x5A, 0x01); // Update Regs // Primary clock configuration -// clocks_mimo_config(MC_WE_DONT_LOCK); + clocks_mimo_config(MC_WE_DONT_LOCK); // Set up other clocks //clocks_enable_test_clk(false, 0); @@ -71,7 +71,7 @@ clocks_init(void) //clocks_enable_adc_clk(true, 1); } -/* + void clocks_mimo_config(int flags) { @@ -116,12 +116,12 @@ clocks_mimo_config(int flags) } // Do we drive a clock onto the MIMO connector? - if (flags & MC_PROVIDE_CLK_TO_MIMO) - clocks_enable_clkexp_out(true,10); - else - clocks_enable_clkexp_out(false,0); +// if (flags & MC_PROVIDE_CLK_TO_MIMO) +// clocks_enable_clkexp_out(true,10); +// else +// clocks_enable_clkexp_out(false,0); } -*/ + /* bool clocks_lock_detect() diff --git a/firmware/microblaze/lib/clocks.h b/firmware/microblaze/lib/clocks.h index 2769fd434..399127595 100644 --- a/firmware/microblaze/lib/clocks.h +++ b/firmware/microblaze/lib/clocks.h @@ -43,7 +43,7 @@ void clocks_init(void); * Configure our master clock source, and whether or not we drive a * clock onto the mimo connector. See MC_flags in usrp2_mimo_config.h. */ -//void clocks_mimo_config(int flags); +void clocks_mimo_config(int flags); /*! * \brief Lock Detect -- Return True if our PLL is locked -- cgit v1.2.3 From f39c4538a3ca25c79f6b793ee0b6448051dcd751 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 29 Jul 2010 10:12:45 -0700 Subject: Clock bugs, LED order. Figured out cold-start problem with Matt's help -- the DCM wasn't being reset. This also explains why USRP2 didn't like it when clocks_mimo_config was omitted -- it was sneakily resetting the DCM while enabling/disabling ref outputs. Also re-did USRP2P LED order and genericized the LED settings so LED_D is LED_D for both USRP2 and USRP2P. --- firmware/microblaze/lib/clocks.c | 23 ++++++++++++++--------- firmware/microblaze/lib/clocks.h | 4 ++-- firmware/microblaze/lib/u2_init.c | 3 ++- firmware/microblaze/usrp2/memory_map.h | 4 ++++ firmware/microblaze/usrp2p/ethernet.c | 4 ++-- firmware/microblaze/usrp2p/memory_map.h | 16 ++++++++++------ 6 files changed, 34 insertions(+), 20 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/clocks.c b/firmware/microblaze/lib/clocks.c index b9bd2e107..2b352a385 100644 --- a/firmware/microblaze/lib/clocks.c +++ b/firmware/microblaze/lib/clocks.c @@ -25,7 +25,6 @@ #include "ad9510.h" #include "spi.h" #include "u2_init.h" -#include "nonstdio.h" //USRP2PLUS clocks: //Clock 0: testclk @@ -46,6 +45,7 @@ clocks_init(void) // Set up basic clocking functions in AD9510 ad9510_write_reg(0x45, 0x01); // CLK2 drives distribution + //enable the 100MHz clock output to the FPGA for 50MHz CPU clock clocks_enable_fpga_clk(true, 1); spi_wait(); @@ -58,7 +58,14 @@ clocks_init(void) // ad9510_write_reg(0x5A, 0x01); // Update Regs // Primary clock configuration - clocks_mimo_config(MC_WE_DONT_LOCK); +// clocks_mimo_config(MC_WE_DONT_LOCK); + + + //wait for the clock to stabilize + while(!clocks_lock_detect()); + + //issue a reset to the DCM so it locks up to the new freq + output_regs->clk_ctrl |= CLK_RESET; // Set up other clocks //clocks_enable_test_clk(false, 0); @@ -71,7 +78,7 @@ clocks_init(void) //clocks_enable_adc_clk(true, 1); } - +/* void clocks_mimo_config(int flags) { @@ -99,7 +106,7 @@ clocks_mimo_config(int flags) spi_wait(); // Allow for clock switchover - + // The below masks include 0x10, which issues a reset to the DCM. if (flags & _MC_WE_LOCK){ // WE LOCK if (flags & _MC_MIMO_CLK_INPUT) { // Turn on ref output and choose the MIMO connector @@ -121,16 +128,14 @@ clocks_mimo_config(int flags) // else // clocks_enable_clkexp_out(false,0); } +*/ -/* bool clocks_lock_detect() { - if(pic_regs->pending & PIC_CLKSTATUS) - return true; - return false; + return (pic_regs->pending & PIC_CLKSTATUS); } -*/ + int inline clocks_gen_div(int divisor) { diff --git a/firmware/microblaze/lib/clocks.h b/firmware/microblaze/lib/clocks.h index 399127595..28d1d542f 100644 --- a/firmware/microblaze/lib/clocks.h +++ b/firmware/microblaze/lib/clocks.h @@ -43,12 +43,12 @@ void clocks_init(void); * Configure our master clock source, and whether or not we drive a * clock onto the mimo connector. See MC_flags in usrp2_mimo_config.h. */ -void clocks_mimo_config(int flags); +//void clocks_mimo_config(int flags); /*! * \brief Lock Detect -- Return True if our PLL is locked */ -//bool clocks_lock_detect(); +bool clocks_lock_detect(); /*! * \brief Enable or disable test clock (extra clock signal) diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index ff558d673..75bc40859 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -26,6 +26,7 @@ #include "mdelay.h" #include "clocks.h" #include "usrp2/fw_common.h" +#include "nonstdio.h" unsigned char u2_hw_rev_major; unsigned char u2_hw_rev_minor; @@ -66,7 +67,7 @@ u2_init(void) mdelay(100); hal_set_leds(0x1f, 0x1f); mdelay(100); - hal_set_leds(0x1, 0x1f); // Leave the first one on + hal_set_leds(LED_D, 0x1f); // Leave one on #if 0 // test register readback diff --git a/firmware/microblaze/usrp2/memory_map.h b/firmware/microblaze/usrp2/memory_map.h index 4c9ead615..41a2820bc 100644 --- a/firmware/microblaze/usrp2/memory_map.h +++ b/firmware/microblaze/usrp2/memory_map.h @@ -375,6 +375,10 @@ typedef struct { volatile uint32_t led_src; // HW or SW control for LEDs } output_regs_t; +#define CLK_RESET (1<<4) +#define CLK_ENABLE (1<<3) | (1<<2) +#define CLK_SEL (1<<1) | (1<<0) + #define SERDES_ENABLE 8 #define SERDES_PRBSEN 4 #define SERDES_LOOPEN 2 diff --git a/firmware/microblaze/usrp2p/ethernet.c b/firmware/microblaze/usrp2p/ethernet.c index 80c303153..660f28934 100644 --- a/firmware/microblaze/usrp2p/ethernet.c +++ b/firmware/microblaze/usrp2p/ethernet.c @@ -70,7 +70,7 @@ ed_link_up(int speed) ed_set_mac_speed(speed); //turn on link LED for USRP2P - hal_set_leds((1 << 0), (1 << 0)); + hal_set_leds(LED_RJ45, LED_RJ45); if (ed_callback) // fire link changed callback @@ -83,7 +83,7 @@ ed_link_down(void) // putstr("ed_link_down\n"); //turn off link LED for USRP2P - hal_set_leds(0, (1 << 0)); + hal_set_leds(0, LED_RJ45); if (ed_callback) // fire link changed callback (*ed_callback)(0); diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h index fc0094e67..9c5b576d7 100644 --- a/firmware/microblaze/usrp2p/memory_map.h +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -402,6 +402,10 @@ typedef struct { volatile uint32_t led_src; // HW or SW control for LEDs } output_regs_t; +#define CLK_RESET (1<<4) +#define CLK_ENABLE (1<<3) | (1<<2) +#define CLK_SEL (1<<1) | (1<<0) + #define SERDES_ENABLE 8 #define SERDES_PRBSEN 4 #define SERDES_LOOPEN 2 @@ -412,13 +416,13 @@ typedef struct { // crazy order that matches the labels on the case -#define LED_A (1 << 4) -#define LED_B (1 << 1) -#define LED_C (1 << 3) -#define LED_D (1 << 0) -#define LED_E (1 << 2) +#define LED_A (1 << 2) +#define LED_B (1 << 5) +#define LED_E (1 << 3) +#define LED_D (1 << 1) +#define LED_C (1 << 4) // LED_F // controlled by CPLD -#define LED_RJ45 (1 << 5) +#define LED_RJ45 (1 << 0) #define output_regs ((output_regs_t *) MISC_OUTPUT_BASE) -- cgit v1.2.3 From dfafbd5f2dbf0758df33d10922eec3c1a37dd32b Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 11 Aug 2010 14:20:50 -0700 Subject: Branch to make use of quad UART on USRP2P. --- firmware/microblaze/lib/hal_io.c | 14 +++++----- firmware/microblaze/lib/hal_uart.c | 48 ++++++++++++++++++++++++--------- firmware/microblaze/lib/hal_uart.h | 8 +++--- firmware/microblaze/usrp2p/memory_map.h | 5 +++- 4 files changed, 50 insertions(+), 25 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index 58b1e681e..b68067308 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -102,7 +102,7 @@ hal_finish(void) // %c inline int -putchar(int ch) +fputchar(int ch) { hal_gpio_set_rx((s << 8) | W, 0xff80); hal_gpio_set_rx(0, 0xff80); @@ -124,14 +124,14 @@ hal_finish(void) // %c inline int -putchar(int ch) +fputchar(int ch) { hal_uart_putc(ch); return ch; } int -getchar(void) +fgetchar(void) { return hal_uart_getc(); } @@ -172,13 +172,13 @@ getchar(void) // \n inline void -newline(void) +fnewline(void) { putchar('\n'); } int -putstr(const char *s) +fputstr(const char *s) { while (*s) putchar(*s++); @@ -187,7 +187,7 @@ putstr(const char *s) } int -puts(const char *s) +fputs(const char *s) { putstr(s); putchar('\n'); @@ -195,7 +195,7 @@ puts(const char *s) } char * -gets(char * const s) +fgets(char * const s) { char *x = s; while((*x=(char)hal_uart_getc()) != '\n') x++; diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index fe3b7515a..91d67b5e0 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -37,28 +37,30 @@ divisor_table[MAX_WB_DIV+1][NSPEEDS] = { { 163, 81, 41, 27, 14, 7 }, // 4: 25 MHz }; -#define u uart_regs +//we wrap hal_uart_putc hal_uart_putc_nowait, and hal_uart_getc to accept a UART pointer given by hal_get_uart. we modify hal_io.c to use the new versions. -static char uart_mode = UART_MODE_ONLCR; +static char uart_mode[4] = {UART_MODE_ONLCR, UART_MODE_ONLCR, UART_MODE_ONLCR, UART_MODE_ONLCR}; void -hal_uart_set_mode(int mode) +hal_uart_set_mode(int uart, int mode) { - uart_mode = mode; + uart_mode[uart] = mode; } void hal_uart_init(void) { - hal_uart_set_mode(UART_MODE_ONLCR); - u->clkdiv = 217; // 230400 bps + for(int i = 0; i < 4; i++) { + hal_uart_set_mode(i, UART_MODE_ONLCR); + u->clkdiv = 217; // 230400 bps TODO: change to reflect new quad UART + } } void -hal_uart_putc(int ch) +hal_uart_putc(uart_regs_t *u, int ch) { - if (ch == '\n')// && (uart_mode == UART_MODE_ONLCR)) //map \n->\r\n if necessary - hal_uart_putc('\r'); + if (ch == '\n')// && (uart_mode[uart] == UART_MODE_ONLCR)) //map \n->\r\n if necessary + hal_uart_putc(u, '\r'); while (u->txlevel == 0) // wait for fifo to have space ; @@ -67,20 +69,40 @@ hal_uart_putc(int ch) } void -hal_uart_putc_nowait(int ch) +hal_uart_putc_nowait(uart_regs_t *u, int ch) { - if (ch == '\n')// && (uart_mode == UART_MODE_ONLCR)) //map \n->\r\n if necessary - hal_uart_putc('\r'); + if (ch == '\n')// && (uart_mode[uart] == UART_MODE_ONLCR)) //map \n->\r\n if necessary + hal_uart_putc(u, '\r'); if(u->txlevel) // If fifo has space u->txchar = ch; } int -hal_uart_getc(void) +hal_uart_getc(uart_regs_t *u) { while ((u->rxlevel) == 0) // wait for data to be ready ; return u->rxchar; } + +uart_regs_t * +hal_get_uart(int number) +{ + switch(number) { + case 0: + return uart_regs_0; + break; + case 1: + return uart_regs_1; + break; + case 2: + return uart_regs_2; + break; + case 3: + return uart_regs_3; + break; + default: + return uart_regs_0; //for safety +} diff --git a/firmware/microblaze/lib/hal_uart.h b/firmware/microblaze/lib/hal_uart.h index dfd73c323..218bd7cb4 100644 --- a/firmware/microblaze/lib/hal_uart.h +++ b/firmware/microblaze/lib/hal_uart.h @@ -28,7 +28,7 @@ /* * \brief Set uart mode */ -void hal_uart_set_mode(int flags); +void hal_uart_set_mode(int uart, int flags); /*! * \brief one-time call to init @@ -62,17 +62,17 @@ void hal_uart_get_config(hal_uart_config_t *c); /*! * \brief Enqueue \p ch for output over serial port */ -void hal_uart_putc(int ch); +void hal_uart_putc(uart_regs_t *u, int ch); /*! * \brief Enqueue \p ch for output over serial port, silent fail if queue is full */ -void hal_uart_putc_nowait(int ch); +void hal_uart_putc_nowait(uart_regs_t *u, int ch); /* * \brief Blocking read of next char from serial port */ -int hal_uart_getc(void); +int hal_uart_getc(uart_regs_t *u); #endif /* INCLUDED_HAL_UART_H */ diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h index 9c5b576d7..b69cc59bd 100644 --- a/firmware/microblaze/usrp2p/memory_map.h +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -781,7 +781,10 @@ typedef struct { volatile uint32_t rxchar; // Read received characters here } uart_regs_t; -#define uart_regs ((uart_regs_t *) UART_BASE) +#define uart_regs_0 ((uart_regs_t *) UART_BASE) +#define uart_regs_1 ((uart_regs_t *) UART_BASE + 0x0020) +#define uart_regs_2 ((uart_regs_t *) UART_BASE + 0x0040) +#define uart_regs_3 ((uart_regs_t *) UART_BASE + 0x0060) /////////////////////////////////////////////////// // ATR Controller, Slave 11 -- cgit v1.2.3 From 32c40b5f5956d29e3be1fc3c94a213f8f0d68f42 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 12 Aug 2010 10:23:33 -0700 Subject: Working support for multiple UARTs. Default behavior (printf, gets, etc.) routes to DEFAULT_UART, set in hal_uart.h. Use fputstr() to print to other UARTs. Bring fgets() from hal_io.c out in hal_io.h if you want to read data from other UARTs. Still blocking. No interrupt-driven stuff yet. --- firmware/microblaze/lib/hal_io.c | 66 ++++++++++++++++++------ firmware/microblaze/lib/hal_io.h | 2 + firmware/microblaze/lib/hal_uart.c | 89 ++++++++++++++++----------------- firmware/microblaze/lib/hal_uart.h | 42 +++++++++------- firmware/microblaze/usrp2p/memory_map.h | 6 +-- 5 files changed, 122 insertions(+), 83 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index b68067308..8bb5e2af8 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -18,9 +18,9 @@ // conditionalized on HAL_IO_USES_DBOARD_PINS && HAL_IO_USES_UART -#include "hal_io.h" #include "memory_map.h" #include "hal_uart.h" +#include "hal_io.h" #include #include #include @@ -102,7 +102,7 @@ hal_finish(void) // %c inline int -fputchar(int ch) +putchar(int ch) { hal_gpio_set_rx((s << 8) | W, 0xff80); hal_gpio_set_rx(0, 0xff80); @@ -124,16 +124,29 @@ hal_finish(void) // %c inline int -fputchar(int ch) +fputchar(hal_uart_name_t u, int ch) +{ + hal_uart_putc(u, ch); + return ch; +} + +inline int +putchar(int ch) { - hal_uart_putc(ch); + hal_uart_putc(DEFAULT_UART, ch); return ch; } int -fgetchar(void) +fgetchar(hal_uart_name_t u) +{ + return hal_uart_getc(u); +} + +int +getchar(void) { - return hal_uart_getc(); + return fgetchar(DEFAULT_UART); } #else // nop all i/o @@ -172,34 +185,57 @@ getchar(void) // \n inline void -fnewline(void) +fnewline(hal_uart_name_t u) { - putchar('\n'); + fputchar(u, '\n'); +} + +inline void +newline(void) +{ + fnewline(DEFAULT_UART); } int -fputstr(const char *s) +fputstr(hal_uart_name_t u, const char *s) { while (*s) - putchar(*s++); + fputchar(u, *s++); return 0; } int -fputs(const char *s) +putstr(const char *s) +{ + return fputstr(DEFAULT_UART, s); +} + +int +fputs(hal_uart_name_t u, const char *s) { - putstr(s); - putchar('\n'); + fputstr(u, s); + fputchar(u, '\n'); return 0; } +int puts(const char *s) +{ + return fputs(DEFAULT_UART, s); +} + char * -fgets(char * const s) +fgets(hal_uart_name_t u, char * const s) { char *x = s; - while((*x=(char)hal_uart_getc()) != '\n') x++; + while((*x=(char)hal_uart_getc(u)) != '\n') x++; *x = 0; return s; } +char * +gets(char * const s) +{ + return fgets(DEFAULT_UART, s); +} + diff --git a/firmware/microblaze/lib/hal_io.h b/firmware/microblaze/lib/hal_io.h index c67d96c62..99f8f7fc9 100644 --- a/firmware/microblaze/lib/hal_io.h +++ b/firmware/microblaze/lib/hal_io.h @@ -20,10 +20,12 @@ #define INCLUDED_HAL_IO_H #include "memory_map.h" +#include "hal_uart.h" void hal_io_init(void); void hal_finish(); char *gets(char * const s); +int fputstr(hal_uart_name_t u, const char *s); /* * ------------------------------------------------------------------------ diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index 91d67b5e0..6717cd5e8 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -16,93 +16,88 @@ * along with this program. If not, see . */ +#include "memory_map.h" #include "hal_uart.h" #include "hal_io.h" -#include "memory_map.h" - -// First pass, no interrupts -// Replaced with divisors.py which generates best divisor -//#define CALC_DIVISOR(rate) (WISHBONE_CLK_RATE / ((rate) * 16)) +//just to save you from going insane, note that firmware/FPGA UARTs [0-2] correspond to serial ports [1-3]. +//so in software, we refer to UART_DEBUG as UART0, but it transmits on pin TXD<1>. see the UART assignments in hal_uart.h. #define NSPEEDS 6 #define MAX_WB_DIV 4 +//if you're going to recalculate the divisors, it's just uart_clock_rate / baud_rate. +//uart_clock_rate is 50MHz for USRP2. static const uint16_t -divisor_table[MAX_WB_DIV+1][NSPEEDS] = { - { 2, 2, 2, 2, 2, 2}, // 0: can't happen - { 651, 326, 163, 109, 54, 27 }, // 1: 100 MHz - { 326, 163, 81, 54, 27, 14 }, // 2: 50 MHz - { 217, 109, 54, 36, 18, 9 }, // 3: 33.3333 MHz - { 163, 81, 41, 27, 14, 7 }, // 4: 25 MHz +divisor_table[NSPEEDS] = { + 5208, // 9600 + 2604, // 19200 + 1302, // 38400 + 868, // 57600 + 434, // 115200 + 217 // 230400 }; -//we wrap hal_uart_putc hal_uart_putc_nowait, and hal_uart_getc to accept a UART pointer given by hal_get_uart. we modify hal_io.c to use the new versions. +static char uart_mode[4] = { + [UART_DEBUG] = UART_MODE_ONLCR, + [UART_EXP] = UART_MODE_ONLCR, + [UART_GPS] = UART_MODE_ONLCR +}; -static char uart_mode[4] = {UART_MODE_ONLCR, UART_MODE_ONLCR, UART_MODE_ONLCR, UART_MODE_ONLCR}; +static char uart_speeds[4] = { + [UART_DEBUG] = US_230400, + [UART_EXP] = US_230400, + [UART_GPS] = US_230400 +}; void -hal_uart_set_mode(int uart, int mode) +hal_uart_set_mode(hal_uart_name_t uart, int mode) { uart_mode[uart] = mode; } +void hal_uart_set_speed(hal_uart_name_t uart, hal_uart_speed_t speed) +{ + uart_regs[uart].clkdiv = divisor_table[speed]; +} + void hal_uart_init(void) { - for(int i = 0; i < 4; i++) { - hal_uart_set_mode(i, UART_MODE_ONLCR); - u->clkdiv = 217; // 230400 bps TODO: change to reflect new quad UART + for(int i = 0; i < 2; i++) { //uart 3 is unused + hal_uart_set_mode(i, uart_mode[i]); + hal_uart_set_speed(i, uart_speeds[i]); } } void -hal_uart_putc(uart_regs_t *u, int ch) +hal_uart_putc(hal_uart_name_t u, int ch) { - if (ch == '\n')// && (uart_mode[uart] == UART_MODE_ONLCR)) //map \n->\r\n if necessary + if ((ch == '\n') && (uart_mode[u] == UART_MODE_ONLCR)) //map \n->\r\n if necessary hal_uart_putc(u, '\r'); - while (u->txlevel == 0) // wait for fifo to have space + while (uart_regs[u].txlevel == 0) // wait for fifo to have space ; - u->txchar = ch; + uart_regs[u].txchar = ch; } void -hal_uart_putc_nowait(uart_regs_t *u, int ch) +hal_uart_putc_nowait(hal_uart_name_t u, int ch) { - if (ch == '\n')// && (uart_mode[uart] == UART_MODE_ONLCR)) //map \n->\r\n if necessary + if ((ch == '\n') && (uart_mode[u] == UART_MODE_ONLCR)) //map \n->\r\n if necessary hal_uart_putc(u, '\r'); - if(u->txlevel) // If fifo has space - u->txchar = ch; + if(uart_regs[u].txlevel) // If fifo has space + uart_regs[u].txchar = ch; } int -hal_uart_getc(uart_regs_t *u) +hal_uart_getc(hal_uart_name_t u) { - while ((u->rxlevel) == 0) // wait for data to be ready + while ((uart_regs[u].rxlevel) == 0) // wait for data to be ready ; - return u->rxchar; + return uart_regs[u].rxchar; } -uart_regs_t * -hal_get_uart(int number) -{ - switch(number) { - case 0: - return uart_regs_0; - break; - case 1: - return uart_regs_1; - break; - case 2: - return uart_regs_2; - break; - case 3: - return uart_regs_3; - break; - default: - return uart_regs_0; //for safety -} diff --git a/firmware/microblaze/lib/hal_uart.h b/firmware/microblaze/lib/hal_uart.h index 218bd7cb4..81f4a6777 100644 --- a/firmware/microblaze/lib/hal_uart.h +++ b/firmware/microblaze/lib/hal_uart.h @@ -25,29 +25,37 @@ #define UART_MODE_RAW 0x0000 // no mapping on input or output #define UART_MODE_ONLCR 0x0001 // map \n to \r\n on output (default) +#define DEFAULT_UART UART_DEBUG //which UART printf, gets, etc. use + +typedef enum { + US_9600 = 0, + US_19200 = 1, + US_38400 = 2, + US_57600 = 3, + US_115200 = 4, + US_230400 = 5 +} hal_uart_speed_t; + +typedef struct { + hal_uart_speed_t speed; +} hal_uart_config_t; + +typedef enum { + UART_DEBUG = 0, + UART_EXP = 1, + UART_GPS = 2 +} hal_uart_name_t; + /* * \brief Set uart mode */ -void hal_uart_set_mode(int uart, int flags); +void hal_uart_set_mode(hal_uart_name_t uart, int flags); /*! * \brief one-time call to init */ void hal_uart_init(void); -typedef enum { - US_9600, - US_19200, - US_38400, - US_57600, - US_115200, - US_230400, -} hal_uart_speed_t; - -typedef struct { - hal_uart_speed_t speed; -} hal_uart_config_t; - /*! * \brief Set uart parameters * Default is 115,200 bps, 8N1. @@ -62,17 +70,17 @@ void hal_uart_get_config(hal_uart_config_t *c); /*! * \brief Enqueue \p ch for output over serial port */ -void hal_uart_putc(uart_regs_t *u, int ch); +void hal_uart_putc(hal_uart_name_t u, int ch); /*! * \brief Enqueue \p ch for output over serial port, silent fail if queue is full */ -void hal_uart_putc_nowait(uart_regs_t *u, int ch); +void hal_uart_putc_nowait(hal_uart_name_t u, int ch); /* * \brief Blocking read of next char from serial port */ -int hal_uart_getc(uart_regs_t *u); +int hal_uart_getc(hal_uart_name_t u); #endif /* INCLUDED_HAL_UART_H */ diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h index b69cc59bd..addcf67d4 100644 --- a/firmware/microblaze/usrp2p/memory_map.h +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -779,12 +779,10 @@ typedef struct { volatile uint32_t rxlevel; // Number of available elements in the FIFO for reads volatile uint32_t txchar; // Write characters to be sent here volatile uint32_t rxchar; // Read received characters here + volatile uint32_t x[3]; //padding to reach 32B } uart_regs_t; -#define uart_regs_0 ((uart_regs_t *) UART_BASE) -#define uart_regs_1 ((uart_regs_t *) UART_BASE + 0x0020) -#define uart_regs_2 ((uart_regs_t *) UART_BASE + 0x0040) -#define uart_regs_3 ((uart_regs_t *) UART_BASE + 0x0060) +#define uart_regs ((uart_regs_t *) UART_BASE) /////////////////////////////////////////////////// // ATR Controller, Slave 11 -- cgit v1.2.3 From e42230e7fae59d91186d21ab6ba8311421649375 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 12 Aug 2010 15:17:58 -0700 Subject: Added UART transactions to the DUDE/BRO protocol. --- firmware/microblaze/apps/txrx_uhd.c | 19 +++++++++++++++++++ firmware/microblaze/lib/hal_io.c | 21 +++++++++++++++++++++ firmware/microblaze/lib/hal_io.h | 2 ++ firmware/microblaze/lib/hal_uart.c | 2 +- host/lib/usrp/usrp2/fw_common.h | 11 +++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) (limited to 'firmware') diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index f0a9702be..42a3f4b89 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -311,6 +311,25 @@ void handle_udp_ctrl_packet( ctrl_data_out.id = USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE; break; + case USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO:{ + //executes a readline()-style read, up to num_bytes long, up to and including newline + int num_bytes = ctrl_data_in->data.uart_args.bytes; + if(num_bytes > 20) num_bytes = 20; + num_bytes = fngets(ctrl_data_in->data.uart_args.dev, (char *) ctrl_data_in->data.uart_args.data, num_bytes); + ctrl_data_out.id = USRP2_CTRL_ID_I_HELLA_READ_THAT_UART_DUDE; + ctrl_data_out.data.uart_args.bytes = num_bytes; + break; + } + + case USRP2_CTRL_ID_HEY_WRITE_THIS_UART_FOR_ME_BRO:{ + int num_bytes = ctrl_data_in->data.uart_args.bytes; + if(num_bytes > 20) num_bytes = 20; + fnputstr(ctrl_data_in->data.uart_args.dev, (char *) ctrl_data_in->data.uart_args.data, num_bytes); + ctrl_data_out.id = USRP2_CTRL_ID_MAN_I_TOTALLY_WROTE_THAT_UART_DUDE; + ctrl_data_out.data.i2c_args.bytes = num_bytes; + break; + } + default: ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index 8bb5e2af8..549990311 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -205,6 +205,18 @@ fputstr(hal_uart_name_t u, const char *s) return 0; } +int +fnputstr(hal_uart_name_t u, const char *s, int len) +{ + int x; + while (*s && (len > x)) { + fputchar(u, *s++); + x++; + } + + return x; +} + int putstr(const char *s) { @@ -233,6 +245,15 @@ fgets(hal_uart_name_t u, char * const s) return s; } +int +fngets(hal_uart_name_t u, char * const s, int len) +{ + char *x = s; + while(((*x=(char)hal_uart_getc(u)) != '\n') && ((x-s) < len)) x++; + *x = 0; + return (x-s)-1; +} + char * gets(char * const s) { diff --git a/firmware/microblaze/lib/hal_io.h b/firmware/microblaze/lib/hal_io.h index 99f8f7fc9..45e23755f 100644 --- a/firmware/microblaze/lib/hal_io.h +++ b/firmware/microblaze/lib/hal_io.h @@ -26,6 +26,8 @@ void hal_io_init(void); void hal_finish(); char *gets(char * const s); int fputstr(hal_uart_name_t u, const char *s); +int fnputstr(hal_uart_name_t u, const char *s, int len); +int fngets(hal_uart_name_t u, char * const s, int len); /* * ------------------------------------------------------------------------ diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index 6717cd5e8..c85bcaca3 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -47,7 +47,7 @@ static char uart_mode[4] = { static char uart_speeds[4] = { [UART_DEBUG] = US_230400, [UART_EXP] = US_230400, - [UART_GPS] = US_230400 + [UART_GPS] = US_115200 }; void diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 85d41d57f..fc1e6f2a7 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -83,6 +83,12 @@ typedef enum{ USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO = 'r', USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE = 'R', + USRP2_CTRL_ID_HEY_WRITE_THIS_UART_FOR_ME_BRO = 'u', + USRP2_CTRL_ID_MAN_I_TOTALLY_WROTE_THAT_UART_DUDE = 'U', + + USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO = 'v', + USRP2_CTRL_ID_I_HELLA_READ_THAT_UART_DUDE = 'V', + USRP2_CTRL_ID_PEACE_OUT = '~' } usrp2_ctrl_id_t; @@ -123,6 +129,11 @@ typedef struct{ __stdint(uint32_t) datahi; __stdint(uint8_t) num_bytes; //1, 2, 4, 8 } poke_args; + struct { + __stdint(uint8_t) dev; + __stdint(uint8_t) bytes; + __stdint(uint8_t) data[20]; + } uart_args; } data; } usrp2_ctrl_data_t; -- cgit v1.2.3 From 6be2b64ce86f4bb9f36bae8758d7de2ddbabe2b1 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 12 Aug 2010 18:13:45 -0700 Subject: Fixed GPS UART stuff. Works OK. --- firmware/microblaze/apps/txrx_uhd.c | 4 ++-- firmware/microblaze/lib/hal_io.c | 6 ++---- firmware/microblaze/lib/hal_uart.c | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 42a3f4b89..2065830ff 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -315,7 +315,7 @@ void handle_udp_ctrl_packet( //executes a readline()-style read, up to num_bytes long, up to and including newline int num_bytes = ctrl_data_in->data.uart_args.bytes; if(num_bytes > 20) num_bytes = 20; - num_bytes = fngets(ctrl_data_in->data.uart_args.dev, (char *) ctrl_data_in->data.uart_args.data, num_bytes); + num_bytes = fngets(ctrl_data_in->data.uart_args.dev, (char *) ctrl_data_out.data.uart_args.data, num_bytes); ctrl_data_out.id = USRP2_CTRL_ID_I_HELLA_READ_THAT_UART_DUDE; ctrl_data_out.data.uart_args.bytes = num_bytes; break; @@ -326,7 +326,7 @@ void handle_udp_ctrl_packet( if(num_bytes > 20) num_bytes = 20; fnputstr(ctrl_data_in->data.uart_args.dev, (char *) ctrl_data_in->data.uart_args.data, num_bytes); ctrl_data_out.id = USRP2_CTRL_ID_MAN_I_TOTALLY_WROTE_THAT_UART_DUDE; - ctrl_data_out.data.i2c_args.bytes = num_bytes; + ctrl_data_out.data.uart_args.bytes = num_bytes; break; } diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index 549990311..18cc34aaf 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -208,11 +208,9 @@ fputstr(hal_uart_name_t u, const char *s) int fnputstr(hal_uart_name_t u, const char *s, int len) { - int x; - while (*s && (len > x)) { + int x = 0; + while (*s && (len > x++)) fputchar(u, *s++); - x++; - } return x; } diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index c85bcaca3..a8344daf5 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -64,7 +64,7 @@ void hal_uart_set_speed(hal_uart_name_t uart, hal_uart_speed_t speed) void hal_uart_init(void) { - for(int i = 0; i < 2; i++) { //uart 3 is unused + for(int i = 0; i < 3; i++) { hal_uart_set_mode(i, uart_mode[i]); hal_uart_set_speed(i, uart_speeds[i]); } -- cgit v1.2.3 From f09d9820ed40371f552d3a910bc2d8170d290653 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 13 Aug 2010 11:34:07 -0700 Subject: first stab at a GPS driver in gps_ctrl.cpp. not the most expandable thing in the world but there's only so many GPS interfaces out there. --- firmware/microblaze/apps/txrx_uhd.c | 3 + firmware/microblaze/lib/hal_uart.c | 7 ++ firmware/microblaze/lib/hal_uart.h | 1 + host/lib/usrp/usrp2/CMakeLists.txt | 2 + host/lib/usrp/usrp2/gps_ctrl.cpp | 140 ++++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/gps_ctrl.hpp | 53 ++++++++++++++ host/lib/usrp/usrp2/mboard_impl.cpp | 7 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 2 + 8 files changed, 209 insertions(+), 6 deletions(-) create mode 100644 host/lib/usrp/usrp2/gps_ctrl.cpp create mode 100644 host/lib/usrp/usrp2/gps_ctrl.hpp (limited to 'firmware') diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 2065830ff..9fe17e262 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -324,6 +324,9 @@ void handle_udp_ctrl_packet( case USRP2_CTRL_ID_HEY_WRITE_THIS_UART_FOR_ME_BRO:{ int num_bytes = ctrl_data_in->data.uart_args.bytes; if(num_bytes > 20) num_bytes = 20; + //before we write to the UART, we flush the receive buffer + //this assumes that we're interested in the reply + hal_uart_rx_flush(ctrl_data_in->data.uart_args.dev); fnputstr(ctrl_data_in->data.uart_args.dev, (char *) ctrl_data_in->data.uart_args.data, num_bytes); ctrl_data_out.id = USRP2_CTRL_ID_MAN_I_TOTALLY_WROTE_THAT_UART_DUDE; ctrl_data_out.data.uart_args.bytes = num_bytes; diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index a8344daf5..8f7f83a68 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -101,3 +101,10 @@ hal_uart_getc(hal_uart_name_t u) return uart_regs[u].rxchar; } +int hal_uart_rx_flush(hal_uart_name_t u) +{ + char x; + while(uart_regs[u].rxlevel) x = uart_regs[u].rxchar; + return x; +} + diff --git a/firmware/microblaze/lib/hal_uart.h b/firmware/microblaze/lib/hal_uart.h index 81f4a6777..051dffe92 100644 --- a/firmware/microblaze/lib/hal_uart.h +++ b/firmware/microblaze/lib/hal_uart.h @@ -82,5 +82,6 @@ void hal_uart_putc_nowait(hal_uart_name_t u, int ch); */ int hal_uart_getc(hal_uart_name_t u); +int hal_uart_rx_flush(hal_uart_name_t u); #endif /* INCLUDED_HAL_UART_H */ diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index b4a90a6ba..47d74cec8 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -26,6 +26,8 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dsp_impl.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.cpp diff --git a/host/lib/usrp/usrp2/gps_ctrl.cpp b/host/lib/usrp/usrp2/gps_ctrl.cpp new file mode 100644 index 000000000..5c015be14 --- /dev/null +++ b/host/lib/usrp/usrp2/gps_ctrl.cpp @@ -0,0 +1,140 @@ +// +// 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 "gps_ctrl.hpp" +#include +#include +#include +#include + +using namespace uhd; +using namespace boost::gregorian; +using namespace boost::posix_time; + +/*! + * A usrp2 GPS control for Jackson Labs devices + */ + +//TODO: multiple baud rate support (requires mboard_impl changes for poking UART registers), NMEA support, better autodetection +class usrp2_gps_ctrl_impl : public usrp2_gps_ctrl{ +public: + usrp2_gps_ctrl_impl(usrp2_iface::sptr iface){ + _iface = iface; + //do init here + //so the Jackson Labs Firefly (and Fury) don't acknowledge successful commands -- only invalid ones. + //first we test to see if there's a Firefly/Fury connected by sending an invalid packet and listening for the response + + std::string reply; + + //TODO: try multiple baud rates (many GPS's are set up for 4800bps, you're fixed at 115200bps 8N1 right now) + //you have to poke registers in order to set baud rate, there's no dude/bro interface for it + _iface->write_uart(GPS_UART, "HAAAY GUYYYYS\n"); + try { + reply = _iface->read_uart(GPS_UART, 20); + } catch (std::runtime_error err) { + if(err.what() != std::string("usrp2 no control response")) throw; //sorry can't cope with that + else { //we don't actually have a GPS installed + gps_type = GPS_TYPE_NONE; + } + } + + if(reply == "Command Error") gps_type = GPS_TYPE_JACKSON_LABS; + else gps_type = GPS_TYPE_NONE; //we'll add NMEA support later + + switch(gps_type) { + case GPS_TYPE_JACKSON_LABS: + //issue some setup stuff so it quits spewing data out when not asked to + //none of these should issue replies so we don't bother looking for it + _iface->write_uart(GPS_UART, "SYST:COMM:SER:"); + _iface->write_uart(GPS_UART, "ECHO OFF\n"); //we split lines before 20 chars right now -- TODO: fix driver to split writes/reads for you + _iface->write_uart(GPS_UART, "SYST:COMM:SER:"); + _iface->write_uart(GPS_UART, "PRO OFF\n"); + _iface->write_uart(GPS_UART, "GPS:GPGGA 0\n"); + _iface->write_uart(GPS_UART, "GPS:GGAST 0\n"); + break; + + case GPS_TYPE_GENERIC_NMEA: + case GPS_TYPE_NONE: + default: + + break; + } + } + + ~usrp2_gps_ctrl_impl(void){ + + } + + ptime get_time(void) { + std::string reply; + ptime now; + switch(gps_type) { + case GPS_TYPE_JACKSON_LABS: + _iface->write_uart(GPS_UART, "PTIME:TIME\n"); + reply = _iface->read_uart(GPS_UART, 20); + now = ptime(get_date(), duration_from_string(reply)); + break; + case GPS_TYPE_GENERIC_NMEA: + case GPS_TYPE_NONE: + default: + throw std::runtime_error("get_time(): Unsupported GPS or no GPS detected\n"); + break; + } + return now; + } + + date get_date(void) { + std::string reply; + date today; + switch(gps_type) { + case GPS_TYPE_JACKSON_LABS: + _iface->write_uart(GPS_UART, "PTIME:DATE\n"); + reply = _iface->read_uart(GPS_UART, 20); + today = from_string(reply); + break; + case GPS_TYPE_GENERIC_NMEA: + case GPS_TYPE_NONE: + default: + throw std::runtime_error("get_date(): Unsupported GPS or no GPS detected\n"); + break; + } + return today; + } + + bool gps_detected(void) { + return (gps_type != GPS_TYPE_NONE); + } + +private: + usrp2_iface::sptr _iface; + + enum { + GPS_TYPE_JACKSON_LABS, + GPS_TYPE_GENERIC_NMEA, + GPS_TYPE_NONE + } gps_type; + + static const int GPS_UART = 2; //TODO: this should be plucked from fw_common.h or memory_map.h or somewhere in common with the firmware + +}; + +/*********************************************************************** + * Public make function for the GPS control + **********************************************************************/ +usrp2_gps_ctrl::sptr usrp2_gps_ctrl::make(usrp2_iface::sptr iface){ + return sptr(new usrp2_gps_ctrl_impl(iface)); +} diff --git a/host/lib/usrp/usrp2/gps_ctrl.hpp b/host/lib/usrp/usrp2/gps_ctrl.hpp new file mode 100644 index 000000000..5936a6fb6 --- /dev/null +++ b/host/lib/usrp/usrp2/gps_ctrl.hpp @@ -0,0 +1,53 @@ +// +// 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 . +// + +#ifndef INCLUDED_GPS_CTRL_HPP +#define INCLUDED_GPS_CTRL_HPP + +#include "usrp2_iface.hpp" +#include +#include +#include + +using namespace boost::posix_time; + +class usrp2_gps_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + /*! + * Make a GPS config for Jackson Labs or generic NMEA GPS devices + */ + static sptr make(usrp2_iface::sptr iface); + + /*! + * Get the current GPS time and date + * \return current GPS time and date as boost::posix_time::ptime object + */ + virtual ptime get_time(void) = 0; + + /*! + * Tell you if there's a supported GPS connected or not + * \return true if a supported GPS is connected + */ + virtual bool gps_detected(void) = 0; + + //TODO: other fun things you can do with a GPS. + +}; + +#endif /* INCLUDED_CLOCK_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 96c98f6c5..ed6398405 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -51,16 +51,11 @@ usrp2_mboard_impl::usrp2_mboard_impl( //set the device revision (USRP2 or USRP2+) based on the above _iface->set_hw_rev((_rev_hi << 8) | _rev_lo); - //TODO DEBUG! this is just here to test writing to and reading from the UART. - std::string mystr = "PTIME:TIME?\n"; - _iface->write_uart(2, mystr); - mystr = _iface->read_uart(2, 20); - std::cout << "what time is it? " << mystr.c_str(); - //contruct the interfaces to mboard perifs _clock_ctrl = usrp2_clock_ctrl::make(_iface); _codec_ctrl = usrp2_codec_ctrl::make(_iface); _serdes_ctrl = usrp2_serdes_ctrl::make(_iface); + _gps_ctrl = usrp2_gps_ctrl::make(_iface); //TODO move to dsp impl... //load the allowed decim/interp rates diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 21a56cb67..b37c61488 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -21,6 +21,7 @@ #include "usrp2_iface.hpp" #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" +#include "gps_ctrl.hpp" #include "serdes_ctrl.hpp" #include #include @@ -151,6 +152,7 @@ private: usrp2_clock_ctrl::sptr _clock_ctrl; usrp2_codec_ctrl::sptr _codec_ctrl; usrp2_serdes_ctrl::sptr _serdes_ctrl; + usrp2_gps_ctrl::sptr _gps_ctrl; //rx and tx dboard methods and objects uhd::usrp::dboard_manager::sptr _dboard_manager; -- cgit v1.2.3 From 6bde8e29eb28b746109531553d38fec91a89dc73 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 13 Aug 2010 12:09:28 -0700 Subject: Added timeout functionality for UART gets() calls. use fngets_timeout(). timeout defined in hal_uart.h. --- firmware/microblaze/apps/txrx_uhd.c | 2 +- firmware/microblaze/lib/hal_io.c | 9 +++++++++ firmware/microblaze/lib/hal_io.h | 1 + firmware/microblaze/lib/hal_uart.c | 11 +++++++++++ firmware/microblaze/lib/hal_uart.h | 7 +++++++ 5 files changed, 29 insertions(+), 1 deletion(-) (limited to 'firmware') diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 9fe17e262..9cf4c163f 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -315,7 +315,7 @@ void handle_udp_ctrl_packet( //executes a readline()-style read, up to num_bytes long, up to and including newline int num_bytes = ctrl_data_in->data.uart_args.bytes; if(num_bytes > 20) num_bytes = 20; - num_bytes = fngets(ctrl_data_in->data.uart_args.dev, (char *) ctrl_data_out.data.uart_args.data, num_bytes); + num_bytes = fngets_timeout(ctrl_data_in->data.uart_args.dev, (char *) ctrl_data_out.data.uart_args.data, num_bytes); ctrl_data_out.id = USRP2_CTRL_ID_I_HELLA_READ_THAT_UART_DUDE; ctrl_data_out.data.uart_args.bytes = num_bytes; break; diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index 18cc34aaf..0e3754958 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -252,6 +252,15 @@ fngets(hal_uart_name_t u, char * const s, int len) return (x-s)-1; } +int +fngets_timeout(hal_uart_name_t u, char * const s, int len) +{ + char *x = s; + while(((*x=(char)hal_uart_getc_timeout(u)) != '\n') && ((x-s) < len)) x++; + *x = 0; + return (x-s)-1; +} + char * gets(char * const s) { diff --git a/firmware/microblaze/lib/hal_io.h b/firmware/microblaze/lib/hal_io.h index 45e23755f..950f8d591 100644 --- a/firmware/microblaze/lib/hal_io.h +++ b/firmware/microblaze/lib/hal_io.h @@ -28,6 +28,7 @@ char *gets(char * const s); int fputstr(hal_uart_name_t u, const char *s); int fnputstr(hal_uart_name_t u, const char *s, int len); int fngets(hal_uart_name_t u, char * const s, int len); +int fngets_timeout(hal_uart_name_t u, char * const s, int len); /* * ------------------------------------------------------------------------ diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index 8f7f83a68..4d754d5e5 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -19,6 +19,7 @@ #include "memory_map.h" #include "hal_uart.h" #include "hal_io.h" +#include "mdelay.h" //just to save you from going insane, note that firmware/FPGA UARTs [0-2] correspond to serial ports [1-3]. //so in software, we refer to UART_DEBUG as UART0, but it transmits on pin TXD<1>. see the UART assignments in hal_uart.h. @@ -101,6 +102,16 @@ hal_uart_getc(hal_uart_name_t u) return uart_regs[u].rxchar; } +int +hal_uart_getc_timeout(hal_uart_name_t u) +{ + int timeout = 0; + while (((uart_regs[u].rxlevel) == 0) && (timeout++ < HAL_UART_TIMEOUT_MS)) + mdelay(1); + + return (uart_regs[u].rxlevel == 0) ? 0 : uart_regs[u].rxchar; +} + int hal_uart_rx_flush(hal_uart_name_t u) { char x; diff --git a/firmware/microblaze/lib/hal_uart.h b/firmware/microblaze/lib/hal_uart.h index 051dffe92..b9b0a5e14 100644 --- a/firmware/microblaze/lib/hal_uart.h +++ b/firmware/microblaze/lib/hal_uart.h @@ -27,6 +27,8 @@ #define DEFAULT_UART UART_DEBUG //which UART printf, gets, etc. use +#define HAL_UART_TIMEOUT_MS 100 + typedef enum { US_9600 = 0, US_19200 = 1, @@ -82,6 +84,11 @@ void hal_uart_putc_nowait(hal_uart_name_t u, int ch); */ int hal_uart_getc(hal_uart_name_t u); +/* + * \brief Blocking read of next char from serial port with timeout + */ +int hal_uart_getc_timeout(hal_uart_name_t u); + int hal_uart_rx_flush(hal_uart_name_t u); #endif /* INCLUDED_HAL_UART_H */ -- cgit v1.2.3 From d96e9f907e17900a59247ba6d28d33c26a1c4468 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 13 Aug 2010 13:07:14 -0700 Subject: Increased UART timeout for slow Jackson Labs GPSDO. Fixed up timeout code. --- firmware/microblaze/lib/hal_io.c | 1 + firmware/microblaze/lib/hal_uart.c | 2 +- firmware/microblaze/lib/hal_uart.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index 0e3754958..f93b20030 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -258,6 +258,7 @@ fngets_timeout(hal_uart_name_t u, char * const s, int len) char *x = s; while(((*x=(char)hal_uart_getc_timeout(u)) != '\n') && ((x-s) < len)) x++; *x = 0; + if(x==s) return 0; return (x-s)-1; } diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index 4d754d5e5..9697f5b20 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -109,7 +109,7 @@ hal_uart_getc_timeout(hal_uart_name_t u) while (((uart_regs[u].rxlevel) == 0) && (timeout++ < HAL_UART_TIMEOUT_MS)) mdelay(1); - return (uart_regs[u].rxlevel == 0) ? 0 : uart_regs[u].rxchar; + return (timeout == HAL_UART_TIMEOUT_MS) ? '\n' : uart_regs[u].rxchar; //return a newline if nothing there, this will trip fngets to quit } int hal_uart_rx_flush(hal_uart_name_t u) diff --git a/firmware/microblaze/lib/hal_uart.h b/firmware/microblaze/lib/hal_uart.h index b9b0a5e14..758c8cb5e 100644 --- a/firmware/microblaze/lib/hal_uart.h +++ b/firmware/microblaze/lib/hal_uart.h @@ -27,7 +27,7 @@ #define DEFAULT_UART UART_DEBUG //which UART printf, gets, etc. use -#define HAL_UART_TIMEOUT_MS 100 +#define HAL_UART_TIMEOUT_MS 300 typedef enum { US_9600 = 0, -- cgit v1.2.3 From ac899c005274ff974565c8ab5c125c51feed4d69 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 13 Aug 2010 16:18:02 -0700 Subject: Small fix for fngets --- firmware/microblaze/lib/hal_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index f93b20030..a8654bce7 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -249,7 +249,7 @@ fngets(hal_uart_name_t u, char * const s, int len) char *x = s; while(((*x=(char)hal_uart_getc(u)) != '\n') && ((x-s) < len)) x++; *x = 0; - return (x-s)-1; + return (x-s); } int @@ -259,7 +259,7 @@ fngets_timeout(hal_uart_name_t u, char * const s, int len) while(((*x=(char)hal_uart_getc_timeout(u)) != '\n') && ((x-s) < len)) x++; *x = 0; if(x==s) return 0; - return (x-s)-1; + return (x-s); } char * -- cgit v1.2.3 From f626a4f21d7301e573bcb601f16bf6ba38352c34 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 13 Aug 2010 17:28:08 -0700 Subject: Fixed behavior when no GPS present. --- firmware/microblaze/lib/hal_io.c | 4 ++-- firmware/microblaze/lib/hal_uart.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index a8654bce7..261c8cc2a 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -256,9 +256,9 @@ int fngets_timeout(hal_uart_name_t u, char * const s, int len) { char *x = s; - while(((*x=(char)hal_uart_getc_timeout(u)) != '\n') && ((x-s) < len)) x++; + + while(((*x=(char)hal_uart_getc_timeout(u)) != '\n') && (*x != -1) && ((x-s) < len)) x++; *x = 0; - if(x==s) return 0; return (x-s); } diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index 9697f5b20..0ac6abd69 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -108,8 +108,7 @@ hal_uart_getc_timeout(hal_uart_name_t u) int timeout = 0; while (((uart_regs[u].rxlevel) == 0) && (timeout++ < HAL_UART_TIMEOUT_MS)) mdelay(1); - - return (timeout == HAL_UART_TIMEOUT_MS) ? '\n' : uart_regs[u].rxchar; //return a newline if nothing there, this will trip fngets to quit + return (timeout == HAL_UART_TIMEOUT_MS) ? -1 : uart_regs[u].rxchar; //return -1 if nothing there, cause fngets to quit } int hal_uart_rx_flush(hal_uart_name_t u) -- cgit v1.2.3 From 40faee2e6d87f7364a0c0c2cf310f1483c0331cf Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Mon, 16 Aug 2010 16:09:52 -0700 Subject: Finished GPS driver, more or less. Should detect any 115kbaud GPS on the serial port, as long as it outputs GPRMC packets. Tweaked the serial driver for a stupid off-by-one mistake. --- firmware/microblaze/lib/hal_io.c | 17 +++--- firmware/microblaze/lib/hal_uart.c | 2 +- host/lib/usrp/usrp2/gps_ctrl.cpp | 116 +++++++++++++++++++++++++++---------- 3 files changed, 97 insertions(+), 38 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/lib/hal_io.c b/firmware/microblaze/lib/hal_io.c index 261c8cc2a..be4c570c7 100644 --- a/firmware/microblaze/lib/hal_io.c +++ b/firmware/microblaze/lib/hal_io.c @@ -237,10 +237,10 @@ int puts(const char *s) char * fgets(hal_uart_name_t u, char * const s) { - char *x = s; - while((*x=(char)hal_uart_getc(u)) != '\n') x++; - *x = 0; - return s; + char *x = s; + while((*x=(char)hal_uart_getc(u)) != '\n') x++; + *x = 0; + return s; } int @@ -248,8 +248,8 @@ fngets(hal_uart_name_t u, char * const s, int len) { char *x = s; while(((*x=(char)hal_uart_getc(u)) != '\n') && ((x-s) < len)) x++; - *x = 0; - return (x-s); + *x = 0; + return (x-s); } int @@ -258,8 +258,9 @@ fngets_timeout(hal_uart_name_t u, char * const s, int len) char *x = s; while(((*x=(char)hal_uart_getc_timeout(u)) != '\n') && (*x != -1) && ((x-s) < len)) x++; - *x = 0; - return (x-s); + *x = 0; + //printf("Returning from fngets() with string %d of length %d\n", s[0], x-s); + return (x-s); } char * diff --git a/firmware/microblaze/lib/hal_uart.c b/firmware/microblaze/lib/hal_uart.c index 0ac6abd69..7836240fe 100644 --- a/firmware/microblaze/lib/hal_uart.c +++ b/firmware/microblaze/lib/hal_uart.c @@ -108,7 +108,7 @@ hal_uart_getc_timeout(hal_uart_name_t u) int timeout = 0; while (((uart_regs[u].rxlevel) == 0) && (timeout++ < HAL_UART_TIMEOUT_MS)) mdelay(1); - return (timeout == HAL_UART_TIMEOUT_MS) ? -1 : uart_regs[u].rxchar; //return -1 if nothing there, cause fngets to quit + return (timeout >= HAL_UART_TIMEOUT_MS) ? -1 : uart_regs[u].rxchar; //return -1 if nothing there, cause fngets to quit } int hal_uart_rx_flush(hal_uart_name_t u) diff --git a/host/lib/usrp/usrp2/gps_ctrl.cpp b/host/lib/usrp/usrp2/gps_ctrl.cpp index 20d670f81..2273b2cd9 100644 --- a/host/lib/usrp/usrp2/gps_ctrl.cpp +++ b/host/lib/usrp/usrp2/gps_ctrl.cpp @@ -33,74 +33,130 @@ using namespace boost::algorithm; * A usrp2 GPS control for Jackson Labs devices */ -//TODO: multiple baud rate support (requires mboard_impl changes for poking UART registers), NMEA support, better autodetection +//TODO: multiple baud rate support (requires mboard_impl changes for poking UART registers) class usrp2_gps_ctrl_impl : public usrp2_gps_ctrl{ public: usrp2_gps_ctrl_impl(usrp2_iface::sptr iface){ _iface = iface; - //do init here - //so the Jackson Labs Firefly (and Fury) don't acknowledge successful commands -- only invalid ones. - //first we test to see if there's a Firefly/Fury connected by sending an invalid packet and listening for the response std::string reply; + bool i_heard_some_nmea = false, i_heard_something_weird = false; - //TODO: try multiple baud rates (many GPS's are set up for 4800bps, you're fixed at 115200bps 8N1 right now) - //you have to poke registers in order to set baud rate, there's no dude/bro interface for it - _iface->read_uart(GPS_UART); //flush it out - _iface->write_uart(GPS_UART, "HAAAY GUYYYYS\n"); - try { - reply = _iface->read_uart(GPS_UART); - //std::cerr << "Got reply from GPS: " << reply.c_str() << " with length = " << reply.length() << std::endl; - } catch (std::runtime_error err) { - if(err.what() != std::string("usrp2 no control response")) throw; //sorry can't cope with that - else { //we don't actually have a GPS installed - gps_type = GPS_TYPE_NONE; + gps_type = GPS_TYPE_NONE; + +// set_uart_baud_rate(GPS_UART, 115200); + //first we look for a Jackson Labs Firefly (since that's what we sell with the USRP2+...) + + _iface->read_uart(GPS_UART); //get whatever junk is in the rx buffer right now, and throw it away + _iface->write_uart(GPS_UART, "HAAAY GUYYYYS\n"); //to elicit a response from the Firefly + + //then we loop until we either timeout, or until we get a response that indicates we're a JL device + int timeout = GPS_TIMEOUT_TRIES; + while(timeout--) { + reply = safe_gps_read(); + if(trim_right_copy(reply) == "Command Error") { + gps_type = GPS_TYPE_JACKSON_LABS; + break; } + else if(reply.substr(0, 3) == "$GP") i_heard_some_nmea = true; //but keep looking for that "Command Error" response + else if(reply.length() != 0) i_heard_something_weird = true; //probably wrong baud rate } - if(trim_right_copy(reply) == "Command Error") gps_type = GPS_TYPE_JACKSON_LABS; - else gps_type = GPS_TYPE_NONE; //we'll add NMEA support later + if((i_heard_some_nmea) && (gps_type != GPS_TYPE_JACKSON_LABS)) gps_type = GPS_TYPE_GENERIC_NMEA; + + //otherwise, we can try some other common baud rates looking to see if a GPS is connected (todo, later) + if((gps_type == GPS_TYPE_NONE) && i_heard_something_weird) { + std::cout << "Invalid reply, possible incorrect baud rate" << std::endl; + } + + bool found_gprmc = false; switch(gps_type) { case GPS_TYPE_JACKSON_LABS: - std::cerr << "Found a Jackson Labs GPS" << std::endl; - //issue some setup stuff so it quits spewing data out when not asked to - //none of these should issue replies so we don't bother looking for it + std::cout << "Found a Jackson Labs GPS" << std::endl; + //issue some setup stuff so it spits out the appropriate data + //none of these should issue replies so we don't bother looking for them //we have to sleep between commands because the JL device, despite not acking, takes considerable time to process each command. - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS)); _iface->write_uart(GPS_UART, "SYST:COMM:SER:ECHO OFF\n"); - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS)); _iface->write_uart(GPS_UART, "SYST:COMM:SER:PRO OFF\n"); - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS)); _iface->write_uart(GPS_UART, "GPS:GPGGA 0\n"); - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS)); _iface->write_uart(GPS_UART, "GPS:GGAST 0\n"); - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS)); _iface->write_uart(GPS_UART, "GPS:GPRMC 1\n"); - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); - break; + boost::this_thread::sleep(boost::posix_time::milliseconds(FIREFLY_STUPID_DELAY_MS)); + +// break; case GPS_TYPE_GENERIC_NMEA: + if(gps_type == GPS_TYPE_GENERIC_NMEA) std::cout << "Found a generic NMEA GPS device" << std::endl; + found_gprmc = false; + //here we loop around looking for a GPRMC packet. if we don't get one, we don't have a usable GPS. + timeout = GPS_TIMEOUT_TRIES; + while(timeout--) { + reply = safe_gps_read(); + if(reply.substr(0, 6) == "$GPRMC") { + found_gprmc = true; + break; + } + } + if(!found_gprmc) { + if(gps_type == GPS_TYPE_JACKSON_LABS) std::cout << "Firefly GPS not locked or warming up." << std::endl; + else std::cout << "GPS does not output GPRMC packets. Cannot retrieve time." << std::endl; + gps_type = GPS_TYPE_NONE; + } + break; + case GPS_TYPE_NONE: default: - break; + } + + } ~usrp2_gps_ctrl_impl(void){ } + std::string safe_gps_read() { + std::string reply; + try { + reply = _iface->read_uart(GPS_UART); + //std::cerr << "Got reply from GPS: " << reply.c_str() << " with length = " << reply.length() << std::endl; + } catch (std::runtime_error err) { + if(err.what() != std::string("usrp2 no control response")) throw; //sorry can't cope with that + else { //we don't actually have a GPS installed + reply = std::string(); + } + } + return reply; + } + ptime get_time(void) { std::string reply; ptime now; boost::tokenizer > tok(reply); std::vector toked; + int timeout = GPS_TIMEOUT_TRIES; + bool found_gprmc = false; switch(gps_type) { case GPS_TYPE_JACKSON_LABS: //deprecated in favor of a single NMEA parser case GPS_TYPE_GENERIC_NMEA: - while(reply.length() == 0) reply = _iface->read_uart(GPS_UART); //loop until we hear something + + while(timeout--) { + reply = safe_gps_read(); + if(reply.substr(0, 6) == "$GPRMC") { + found_gprmc = true; + break; + } + } + UHD_ASSERT_THROW(found_gprmc); + tok.assign(reply); toked.assign(tok.begin(), tok.end()); @@ -138,6 +194,8 @@ private: } gps_type; static const int GPS_UART = 2; //TODO: this should be plucked from fw_common.h or memory_map.h or somewhere in common with the firmware + static const int GPS_TIMEOUT_TRIES = 5; + static const int FIREFLY_STUPID_DELAY_MS = 200; }; -- cgit v1.2.3 From 9d10efa5f0f81e1a971e92b28ba7f38e0384fdab Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 17 Aug 2010 18:35:11 -0700 Subject: UDP firmware update support for USRP2P. The hooks are in there for USRP2, but without CPLD changes it won't support it. Added an app host/utils/usrp2p_fw_update.py to write to USRP2P over the wire. Lots of TODOs in that file. Caveat -- fw_common.h, bootloader_utils.h, and the .py app MUST ALL AGREE! --- firmware/microblaze/apps/txrx_uhd.c | 2 + firmware/microblaze/lib/loader_parser.c | 324 ---------------------------- firmware/microblaze/lib/loader_parser.h | 38 ---- firmware/microblaze/lib/udp_burner_packet.c | 38 ---- firmware/microblaze/lib/udp_burner_packet.h | 28 --- firmware/microblaze/usrp2/Makefile.am | 3 +- firmware/microblaze/usrp2/udp_fw_update.c | 34 +++ firmware/microblaze/usrp2/udp_fw_update.h | 22 ++ firmware/microblaze/usrp2p/Makefile.am | 4 +- firmware/microblaze/usrp2p/spi_flash.h | 7 + firmware/microblaze/usrp2p/spi_flash_read.c | 19 ++ firmware/microblaze/usrp2p/udp_fw_update.c | 116 ++++++++++ firmware/microblaze/usrp2p/udp_fw_update.h | 22 ++ host/lib/usrp/usrp2/fw_common.h | 50 ++++- host/utils/usrp2p_fw_update.py | 259 ++++++++++++++++++++++ 15 files changed, 535 insertions(+), 431 deletions(-) delete mode 100644 firmware/microblaze/lib/loader_parser.c delete mode 100644 firmware/microblaze/lib/loader_parser.h delete mode 100644 firmware/microblaze/lib/udp_burner_packet.c delete mode 100644 firmware/microblaze/lib/udp_burner_packet.h create mode 100644 firmware/microblaze/usrp2/udp_fw_update.c create mode 100644 firmware/microblaze/usrp2/udp_fw_update.h create mode 100644 firmware/microblaze/usrp2p/udp_fw_update.c create mode 100644 firmware/microblaze/usrp2p/udp_fw_update.h create mode 100755 host/utils/usrp2p_fw_update.py (limited to 'firmware') diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 9cf4c163f..e637cb38c 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -45,6 +45,7 @@ #include #include #include +#include "udp_fw_update.h" /* * Full duplex Tx and Rx between ethernet and DSP pipelines @@ -474,6 +475,7 @@ main(void) register_udp_listener(USRP2_UDP_CTRL_PORT, handle_udp_ctrl_packet); register_udp_listener(USRP2_UDP_DATA_PORT, handle_udp_data_packet); + register_udp_listener(USRP2_UDP_UPDATE_PORT, handle_udp_fw_update_packet); // initialize double buffering state machine for ethernet -> DSP Tx diff --git a/firmware/microblaze/lib/loader_parser.c b/firmware/microblaze/lib/loader_parser.c deleted file mode 100644 index 96457a164..000000000 --- a/firmware/microblaze/lib/loader_parser.c +++ /dev/null @@ -1,324 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 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 "loader_parser.h" -#include -#include -#include -#include -#include -//#include -#include -#include -#include -#include "ethernet.h" -#include "qr_settings.h" - -#define min(a,b) ((a) < (b) ? (a) : (b)) - -static spi_flash_async_state_t async_state; - - -static caldiv_eeprom_setter_t _caldiv_set_rev = NULL; -static caldiv_eeprom_setter_t _caldiv_set_ser = NULL; -static caldiv_eeprom_setter_t _caldiv_set_mod = NULL; - -void -register_caldiv_eeprom_setters(caldiv_eeprom_setter_t set_rev, - caldiv_eeprom_setter_t set_ser, - caldiv_eeprom_setter_t set_mod) -{ - _caldiv_set_rev = set_rev; - _caldiv_set_ser = set_ser; - _caldiv_set_mod = set_mod; -} - - -// big-endian -static uint32_t -get32(const unsigned char *s) -{ - return (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; -} - -// big-endian -static unsigned char * -put32(unsigned char *s, uint32_t v) -{ - s[0] = (v >> 24) & 0xff; - s[1] = (v >> 16) & 0xff; - s[2] = (v >> 8) & 0xff; - s[3] = v & 0xff; - return s + 4; -} - -static bool -erased_p(uint32_t flash_addr, size_t nbytes) -{ - unsigned char buf[64]; - - size_t n; - for (size_t i = 0; i < nbytes; i += n, flash_addr += n){ - n = min(nbytes - i, sizeof(buf)); - spi_flash_read(flash_addr, n, buf); - for (size_t j = 0; j < n; j++) - if (buf[j] != 0xff) - return false; - } - return true; -} - -static bool -erase_flash(uint32_t addr, uint32_t len) -{ - if (addr % spi_flash_sector_size() != 0) - return false; - - if (len % spi_flash_sector_size() != 0) - return false; - - spi_flash_async_erase_start(&async_state, addr, len); - // FIXME? check to see if erase was successful - return true; -} - -static bool -map_slot(uint32_t slot, uint32_t *slot_start, uint32_t *slot_len, uint32_t *status) -{ - // This case doesn't require a valid flashdir, and in fact can be used as - // part of writing the intial flashdir. - if (QLD_SLOT_DOM(slot) == QLD_DOM_UNMAPPED){ - int flash_size = get_flash_size(); - if (flash_size == 0){ - *status = QLDS_FAILED; // Can't find the flash. most likely a h/w problem. - return false; - } - *slot_start = 0; - *slot_len = flash_size; - return true; - } - - const struct flashdir *fd = get_flashdir(); - if (fd == 0) - return false; - - uint32_t slot_num = QLD_SLOT_NUM(slot); - - switch(QLD_SLOT_DOM(slot)){ - case QLD_DOM_FPGA: - if (slot_num >= fd->fpga_nslots){ - *status = QLDS_INVALID_ARG; - return false; - } - *slot_start = fd->slot[slot_num + fd->fpga_slot0].start << spi_flash_log2_sector_size(); - *slot_len = fd->slot[slot_num + fd->fpga_slot0].len << spi_flash_log2_sector_size(); - return true; - - case QLD_DOM_FW: - if (slot_num >= fd->fw_nslots){ - *status = QLDS_INVALID_ARG; - return false; - } - *slot_start = fd->slot[slot_num + fd->fw_slot0].start << spi_flash_log2_sector_size(); - *slot_len = fd->slot[slot_num + fd->fw_slot0].len << spi_flash_log2_sector_size(); - return true; - - default: - *status = QLDS_INVALID_ARG; - return false; - } -} - - -static bool -check_flashdir(void) -{ - return get_flashdir() != 0; -} - -void -loader_parser(const unsigned char *input, size_t ilen, - unsigned char *output, size_t max_olen, size_t *actual_olen) -{ - //assert (max_olen >= 8); - if (!(max_olen >= 8)) - abort(); - - *actual_olen = 0; - uint32_t status = QLDS_BAD_PKT; - - uint32_t cmd = get32(input); - uint32_t nonce = get32(input+4); - uint32_t slot = 0; - uint32_t addr = 0; - uint32_t len = 0; - - if (ilen < 8){ - nonce = -1; - goto done; - } - - uint32_t slot_start; // offset in flash - uint32_t slot_len; // length in bytes - - if (ilen >= 5 * sizeof(uint32_t)){ - slot = get32(input+8); - addr = get32(input+12); - len = get32(input+16); - } - - switch (cmd){ - case QLD_FLASH_ERASE_START: - // - if (ilen != 5 * sizeof(uint32_t)) - goto done; - - if (!check_flashdir()){ - status = QLDS_BAD_FLASHDIR; - goto done; - } - if (!map_slot(slot, &slot_start, &slot_len, &status)) - goto done; - - if (QLD_SLOT_DOM(slot) != QLD_DOM_UNMAPPED){ - addr = slot_start; - len = slot_len; - } - //printf("flash_erase: addr = 0x%x, len=0x%x\n", addr, len); - - if (0 && erased_p(addr, len)){ // already erased? - async_state.first = async_state.last = async_state.current = 0; - goto ok; - } - - if (erase_flash(addr, len)) - goto ok; - - status = QLDS_FAILED; - goto done; - - - case QLD_FLASH_ERASE_POLL: - // - if (ilen != 2 * sizeof(uint32_t)) - goto done; - - if (spi_flash_async_erase_poll(&async_state)) - goto ok; - - status = QLDS_BUSY; - goto done; - - - case QLD_FLASH_WRITE: - // - if (ilen < 5 * sizeof(uint32_t)) - goto done; - - if (ilen != 5 * sizeof(uint32_t) + len) - goto done; - - if (!check_flashdir()){ - status = QLDS_BAD_FLASHDIR; - goto done; - } - if (!map_slot(slot, &slot_start, &slot_len, &status)) - goto done; - - addr += slot_start; - len = min(len, slot_len); - - if (spi_flash_program(addr, len, &input[5*sizeof(uint32_t)])) - goto ok; - - status = QLDS_FAILED; - goto done; - - - case QLD_FLASH_READ: - case QLD_MEM_READ: - case QLD_MEM_WRITE: - case QLD_GOTO: - status = QLDS_NOTIMPLEMENTED; - goto done; - - case QLD_PING: - // - if (ilen != 2 * sizeof(uint32_t)) - goto done; - goto ok; - -#if 0 - case QLD_EEPROM_SET_XXX: - // - { - uint32_t arg = get32(input+2*sizeof(uint32_t)); - uint32_t idlen = get32(input+3*sizeof(uint32_t)); - uint8_t *idstr = (uint8_t*)input+4*sizeof(uint32_t); - uint8_t *data_p = idstr+idlen; - - //handle the ethernet cases - if (strncmp((char*)idstr, "ip", idlen) == 0){ - struct ip_addr addr = {get32(data_p)}; - ethernet_set_ip_addr(arg, addr); - } - else if (strncmp((char*)idstr, "mac", idlen) == 0){ - eth_mac_addr_t addr; - memcpy(&addr, data_p, sizeof(addr)); - ethernet_set_mac_addr(arg, &addr); - } - //handle the main board eeprom - else if (strncmp((char*)idstr, "qrrev", idlen) == 0){ - qr_set_revision(get32(data_p)); - } - else if (strncmp((char*)idstr, "qrser", idlen) == 0){ - qr_set_serial(get32(data_p)); - } - else if (strncmp((char*)idstr, "qrmod", idlen) == 0){ - qr_set_model(get32(data_p)); - } - //handle the caldiv eeprom - else if (strncmp((char*)idstr, "cdrev", idlen) == 0){ - if (_caldiv_set_rev) _caldiv_set_rev(get32(data_p)); - } - else if (strncmp((char*)idstr, "cdser", idlen) == 0){ - if (_caldiv_set_ser) _caldiv_set_ser(get32(data_p)); - } - else if (strncmp((char*)idstr, "cdmod", idlen) == 0){ - if (_caldiv_set_ser) _caldiv_set_mod(get32(data_p)); - } - else { - goto done; - } - } - goto ok; -#endif - - default: - status = QLDS_UNKNOWN_CMD; - goto done; - } - - ok: - status = QLDS_OK; - - done: - put32(output, nonce); - put32(output+4, status); - *actual_olen = 2*sizeof(uint32_t); -} diff --git a/firmware/microblaze/lib/loader_parser.h b/firmware/microblaze/lib/loader_parser.h deleted file mode 100644 index 365317bd7..000000000 --- a/firmware/microblaze/lib/loader_parser.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 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 - -/* - * max_olen must be at least 8 bytes. 1KB is recommended. - */ -void -loader_parser(const unsigned char *input, size_t ilen, - unsigned char *output, size_t max_olen, size_t *actual_olen); - -/* - * Major kludge-master altert! - * This function registers functions for setting caldiv eeprom stuff. - * This way, the parser does not depend on the qpn apps at compile time. - */ -typedef void(*caldiv_eeprom_setter_t)(uint32_t); -void register_caldiv_eeprom_setters( - caldiv_eeprom_setter_t set_rev, - caldiv_eeprom_setter_t set_ser, - caldiv_eeprom_setter_t set_mod); diff --git a/firmware/microblaze/lib/udp_burner_packet.c b/firmware/microblaze/lib/udp_burner_packet.c deleted file mode 100644 index d86a4cf4a..000000000 --- a/firmware/microblaze/lib/udp_burner_packet.c +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 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 . - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include "udp_burner_packet.h" -#include "net_common.h" -#include "loader_parser.h" -#include -#include -#include - - -void -handle_udp_burner_packet(struct socket_address src, struct socket_address dst, - unsigned char *payload, int payload_len) -{ - unsigned char reply[128] _AL4; - size_t actual_reply_len; - loader_parser(payload, payload_len, reply, sizeof(reply), &actual_reply_len); - send_udp_pkt(dst.port, src, reply, actual_reply_len); -} diff --git a/firmware/microblaze/lib/udp_burner_packet.h b/firmware/microblaze/lib/udp_burner_packet.h deleted file mode 100644 index 0f4025712..000000000 --- a/firmware/microblaze/lib/udp_burner_packet.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 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 . - */ -#ifndef INCLUDED_UDP_BURNER_PACKET_H -#define INCLUDED_UDP_BURNER_PACKET_H - -#include - -void -handle_udp_burner_packet(struct socket_address src, struct socket_address dst, - unsigned char *payload, int payload_len); - - -#endif /* INCLUDED_UDP_BURNER_PACKET_H */ diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am index 8da013980..17f7a4744 100644 --- a/firmware/microblaze/usrp2/Makefile.am +++ b/firmware/microblaze/usrp2/Makefile.am @@ -34,7 +34,8 @@ noinst_LIBRARIES = libusrp2.a libusrp2_a_SOURCES = \ $(COMMON_SRCS) \ sd.c \ - ethernet.c + ethernet.c \ + udp_fw_update.c noinst_PROGRAMS = \ usrp2_txrx_uhd.elf diff --git a/firmware/microblaze/usrp2/udp_fw_update.c b/firmware/microblaze/usrp2/udp_fw_update.c new file mode 100644 index 000000000..bd62aed85 --- /dev/null +++ b/firmware/microblaze/usrp2/udp_fw_update.c @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * 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 . + */ + +//Routines to handle updating the SPI Flash firmware via UDP + +#include "net_common.h" +#include "usrp2/fw_common.h" +#include "udp_fw_update.h" +#include + +//Firmware update packet handler +void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, + unsigned char *payload, int payload_len) { + + udp_fw_update_data_t update_data_out; + update_data_out.id = USRP2_FW_UPDATE_ID_WAT; + + send_udp_pkt(USRP2_UDP_UPDATE_PORT, src, &update_data_out, sizeof(update_data_out)); +} diff --git a/firmware/microblaze/usrp2/udp_fw_update.h b/firmware/microblaze/usrp2/udp_fw_update.h new file mode 100644 index 000000000..dcf44bc42 --- /dev/null +++ b/firmware/microblaze/usrp2/udp_fw_update.h @@ -0,0 +1,22 @@ +/* -*- c++ -*- */ +/* + * 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 "net_common.h" + +void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, + unsigned char *payload, int payload_len); diff --git a/firmware/microblaze/usrp2p/Makefile.am b/firmware/microblaze/usrp2p/Makefile.am index ddc7006ca..c9ed3b99b 100644 --- a/firmware/microblaze/usrp2p/Makefile.am +++ b/firmware/microblaze/usrp2p/Makefile.am @@ -32,6 +32,7 @@ COMMON_IHX_ARGS = \ --change-section-address .vectors.hw_exception+0x8000 \ --change-section-address .vectors.interrupt+0x8000 \ --change-section-address .vectors.reset+0x8000 + # $(MB_OBJCOPY) -O ihex $< $@ # the below would work if objcopy weren't written by apes # $(MB_OBJCOPY) -O ihex -w --change-section-address .vectors*+0x8000 $< $@ @@ -49,7 +50,8 @@ libusrp2p_a_SOURCES = \ spi_flash.c \ spi_flash_read.c \ bootloader_utils.c \ - ethernet.c + ethernet.c \ + udp_fw_update.c noinst_PROGRAMS = \ usrp2p_txrx_uhd.elf \ diff --git a/firmware/microblaze/usrp2p/spi_flash.h b/firmware/microblaze/usrp2p/spi_flash.h index f65f28477..bbe7b650d 100644 --- a/firmware/microblaze/usrp2p/spi_flash.h +++ b/firmware/microblaze/usrp2p/spi_flash.h @@ -31,6 +31,7 @@ uint32_t spi_flash_rdid(void); /* Read ID */ uint32_t spi_flash_rdsr(void); /* Read Status Register */ size_t spi_flash_log2_sector_size(void) __attribute__((pure)); /* either 16 or 18 */ +size_t spi_flash_log2_memory_size(void); static inline size_t spi_flash_sector_size(void) @@ -38,6 +39,12 @@ spi_flash_sector_size(void) return ((size_t) 1) << spi_flash_log2_sector_size(); } +static inline size_t +spi_flash_memory_size(void) +{ + return ((size_t) 1) << spi_flash_log2_memory_size(); +} + void spi_flash_read(uint32_t flash_addr, size_t nbytes, void *buf); /* diff --git a/firmware/microblaze/usrp2p/spi_flash_read.c b/firmware/microblaze/usrp2p/spi_flash_read.c index 1c65350f7..4682c5fe6 100644 --- a/firmware/microblaze/usrp2p/spi_flash_read.c +++ b/firmware/microblaze/usrp2p/spi_flash_read.c @@ -20,6 +20,8 @@ #include "spi_flash_private.h" #include // abort +static size_t _spi_flash_log2_memory_size; + uint32_t spi_flash_rdid(void) { @@ -48,9 +50,26 @@ spi_flash_log2_sector_size(void) }; _spi_flash_log2_sector_size = log2_sector_size[size - 22]; + _spi_flash_log2_memory_size = size; //while we're at it return _spi_flash_log2_sector_size; } +size_t +spi_flash_log2_memory_size(void) +{ + if (_spi_flash_log2_memory_size != 0) + return _spi_flash_log2_memory_size; + + uint32_t id = spi_flash_rdid(); + int type = (id >> 8) & 0xff; + int size = id & 0xff; + if (type != 0x20 || size < 22 || size > 24) + abort(); + + _spi_flash_log2_memory_size = size; + return _spi_flash_log2_memory_size; +} + void spi_flash_read(uint32_t flash_addr, size_t nbytes, void *buf) { diff --git a/firmware/microblaze/usrp2p/udp_fw_update.c b/firmware/microblaze/usrp2p/udp_fw_update.c new file mode 100644 index 000000000..6b860007a --- /dev/null +++ b/firmware/microblaze/usrp2p/udp_fw_update.c @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * 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 . + */ + +//Routines to handle updating the SPI Flash firmware via UDP + +#include +#include "usrp2/fw_common.h" +#include "spi.h" +#include "spi_flash.h" +#include "udp_fw_update.h" +#include +#include +#include "ethernet.h" + +//Firmware update packet handler +void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, + unsigned char *payload, int payload_len) { +//okay, we can do this ANY NUMBER of ways. we have up to ~1500 bytes to play with -- we don't handle +//fragmentation, so limit it to id; + + //ensure that the protocol versions match + if (payload_len >= sizeof(uint32_t) && update_data_in->proto_ver != USRP2_FW_COMPAT_NUM){ + printf("!Error in update packet handler: Expected compatibility number %d, but got %d\n", + USRP2_FW_COMPAT_NUM, update_data_in->proto_ver + ); + update_data_in_id = USRP2_FW_UPDATE_ID_OHAI_LOL; //so we can respond + } + + //ensure that this is not a short packet + if (payload_len < sizeof(udp_fw_update_data_t)){ + printf("!Error in update packet handler: Expected payload length %d, but got %d\n", + (int)sizeof(udp_fw_update_data_t), payload_len + ); + update_data_in_id = USRP2_FW_UPDATE_ID_WAT; + } + + spi_flash_async_state_t spi_flash_async_state; + + switch(update_data_in_id) { + case USRP2_FW_UPDATE_ID_OHAI_LOL: //why hello there you handsome devil + update_data_out.id = USRP2_FW_UPDATE_ID_OHAI_OMG; + memcpy(&update_data_out.data.ip_addr, (void *)get_ip_addr(), sizeof(struct ip_addr)); + break; + + case USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL: //query sector size, memory size so the host can mind the boundaries + update_data_out.data.flash_info_args.sector_size_bytes = spi_flash_sector_size(); + update_data_out.data.flash_info_args.memory_size_bytes = spi_flash_memory_size(); + update_data_out.id = USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG; + break; + + case USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL: //out with the old + spi_flash_async_erase_start(&spi_flash_async_state, update_data_in->data.flash_args.flash_addr, update_data_in->data.flash_args.length); + update_data_out.id = USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG; + break; + + case USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL: + //poll for done, set something in the reply packet + //spi_flash_async_erase_poll() also advances the state machine, so you should call it reasonably often to get things done quicker + if(spi_flash_async_erase_poll(&spi_flash_async_state)) update_data_out.id = USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG; + else update_data_out.id = USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG; + break; + + case USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL: //and in with the new + //spi_flash_program() goes pretty quick compared to page erases, so we don't bother polling -- it'll come back in some milliseconds + //if it doesn't come back fast enough, we'll just write smaller packets at a time until it does + spi_flash_program(update_data_in->data.flash_args.flash_addr, update_data_in->data.flash_args.length, update_data_in->data.flash_args.data); + update_data_out.id = USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG; + break; + + case USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL: //for verify + spi_flash_read(update_data_in->data.flash_args.flash_addr, update_data_in->data.flash_args.length, update_data_out.data.flash_args.data); + update_data_out.id = USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG; + break; + + case USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL: //for if we ever get the ICAP working + //should reset via icap_reload_fpga(uint32_t flash_address); + update_data_out.id = USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG; + //you should note that if you get a reply packet to this the reset has obviously failed + break; + +// case USRP2_FW_UPDATE_ID_KTHXBAI: //see ya +// break; + + default: //uhhhh + update_data_out.id = USRP2_FW_UPDATE_ID_WAT; + } + send_udp_pkt(USRP2_UDP_UPDATE_PORT, src, &update_data_out, sizeof(update_data_out)); +} diff --git a/firmware/microblaze/usrp2p/udp_fw_update.h b/firmware/microblaze/usrp2p/udp_fw_update.h new file mode 100644 index 000000000..dcf44bc42 --- /dev/null +++ b/firmware/microblaze/usrp2p/udp_fw_update.h @@ -0,0 +1,22 @@ +/* -*- c++ -*- */ +/* + * 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 "net_common.h" + +void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, + unsigned char *payload, int payload_len); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index fc1e6f2a7..320ed7d77 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -34,7 +34,7 @@ extern "C" { //fpga and firmware compatibility numbers #define USRP2_FPGA_COMPAT_NUM 1 -#define USRP2_FW_COMPAT_NUM 5 +#define USRP2_FW_COMPAT_NUM 6 //used to differentiate control packets over data port #define USRP2_INVALID_VRT_HEADER 0 @@ -43,6 +43,7 @@ extern "C" { // Dynamic and/or private ports: 49152-65535 #define USRP2_UDP_CTRL_PORT 49152 #define USRP2_UDP_DATA_PORT 49153 +#define USRP2_UDP_UPDATE_PORT 49154 //for firmware upgrade commands //////////////////////////////////////////////////////////////////////// // I2C addresses @@ -93,6 +94,35 @@ typedef enum{ } usrp2_ctrl_id_t; +typedef enum { + USRP2_FW_UPDATE_ID_WAT = ' ', + + USRP2_FW_UPDATE_ID_OHAI_LOL = 'a', + USRP2_FW_UPDATE_ID_OHAI_OMG = 'A', + + USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL = 'f', + USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG = 'F', + + USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL = 'e', + USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG = 'E', + + USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL = 'd', + USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG = 'D', + USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG = 'B', + + USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL = 'w', + USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG = 'W', + + USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL = 'r', + USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG = 'R', + + USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL = 's', + USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG = 'S', + + USRP2_FW_UPDATE_ID_KTHXBAI = '~' + +} usrp2_fw_update_id_t; + typedef enum{ USRP2_DIR_RX = 'r', USRP2_DIR_TX = 't' @@ -137,6 +167,24 @@ typedef struct{ } data; } usrp2_ctrl_data_t; +typedef struct { + __stdint(uint32_t) proto_ver; + __stdint(uint32_t) id; + __stdint(uint32_t) seq; + union { + __stdint(uint32_t) ip_addr; + struct { + __stdint(uint32_t) flash_addr; + __stdint(uint32_t) length; + __stdint(uint8_t) data[256]; + } flash_args; + struct { + __stdint(uint32_t) sector_size_bytes; + __stdint(uint32_t) memory_size_bytes; + } flash_info_args; + } data; +} udp_fw_update_data_t; + #undef __stdint #ifdef __cplusplus } diff --git a/host/utils/usrp2p_fw_update.py b/host/utils/usrp2p_fw_update.py new file mode 100755 index 000000000..dce9c82ef --- /dev/null +++ b/host/utils/usrp2p_fw_update.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python +# +# 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 . +# + +# TODO: make it work +# TODO: make it autodetect UHD devices +# TODO: you should probably watch sequence numbers + +import optparse +import math +import os +import re +import struct +import socket +import sys + +######################################################################## +# constants +######################################################################## +UDP_FW_UPDATE_PORT = 49154 +UDP_MAX_XFER_BYTES = 1024 +UDP_TIMEOUT = 3 +UDP_POLL_INTERVAL = 0.10 #in seconds + +USRP2_FW_PROTO_VERSION = 5 + +#from bootloader_utils.h +PROD_FPGA_IMAGE_LOCATION_ADDR = 0x00200000 +PROD_FW_IMAGE_LOCATION_ADDR = 0x00400000 +SAFE_FW_IMAGE_LOCATION_ADDR = 0x007F0000 +SAFE_FPGA_IMAGE_LOCATION_ADDR = 0x00000000 +FPGA_IMAGE_SIZE_BYTES = 2097152 +FW_IMAGE_SIZE_BYTES = 31744 + +FLASH_DATA_PACKET_SIZE = 256 + +#see fw_common.h +FLASH_ARGS_FMT = '!LLLLL256s' +FLASH_INFO_FMT = '!LLLLL256x' +FLASH_IP_FMT = '!LLLL260x' + +class update_id_t: + USRP2_FW_UPDATE_ID_WAT = ord(' ') + USRP2_FW_UPDATE_ID_OHAI_LOL = ord('a') + USRP2_FW_UPDATE_ID_OHAI_OMG = ord('A') + USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL = ord('f') + USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG = ord('F') + USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL = ord('e') + USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG = ord('E') + USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL = ord('d') + USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG = ord('D') + USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG = ord('B') + USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL = ord('w') + USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG = ord('W') + USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL = ord('r') + USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG = ord('R') + USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL = ord('s') + USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG = ord('S') + USRP2_FW_UPDATE_ID_KTHXBAI = ord('~') + +_seq = -1 +def seq(): + global _seq + _seq = _seq+1 + return _seq + +######################################################################## +# helper functions +######################################################################## +def unpack_flash_args_fmt(s): + return struct.unpack(FLASH_ARGS_FMT, s) #(proto_ver, pktid, seq, flash_addr, length, data) + +def unpack_flash_info_fmt(s): + return struct.unpack(FLASH_INFO_FMT, s) #(proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes) + +def unpack_flash_ip_fmt(s): + return struct.unpack(FLASH_IP_FMT, s) #(proto_ver, pktid, seq, ip_addr) + +def pack_flash_args_fmt(proto_ver, pktid, seq, flash_addr, length, data): + return struct.pack(FLASH_ARGS_FMT, proto_ver, pktid, seq, flash_addr, length, data) + +def pack_flash_info_fmt(proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes): + return struct.pack(FLASH_INFO_FMT, proto_ver, pktid, seq, sector_size_bytes, memory_size_bytes) + +def send_and_recv(pkt, ip): + update_socket = create_socket() + + try: + update_socket.sendto(pkt, (ip, UDP_FW_UPDATE_PORT)) + except Exception, e: + print e + sys.exit(1) + + try: + (recv_pkt, recv_addr) = update_socket.recvfrom(UDP_MAX_XFER_BYTES) + except Exception, e: + print e + sys.exit(1) + + if recv_addr != (options.ip, UDP_FW_UPDATE_PORT): + raise Exception, "Packet received from invalid IP %s, expected %s" % (recv_addr, options.ip) + + return recv_pkt + +def create_socket(): + socket.setdefaulttimeout(UDP_TIMEOUT) + update_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return update_socket + +#just here to validate comms +def init_update(ip): + out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_OHAI_LOL, seq(), 0, 0, "") + in_pkt = send_and_recv(out_pkt, ip) + (proto_ver, pktid, rxseq, ip_addr) = unpack_flash_ip_fmt(in_pkt) + if pktid == update_id_t.USRP2_FW_UPDATE_ID_OHAI_OMG: + print "USRP2P found." + else: + raise Exception, "Invalid reply received from device." + +# print "Incoming:\n\tVer: %i\n\tID: %c\n\tSeq: %i\n\tIP: %i\n" % (proto_ver, chr(pktid), rxseq, ip_addr) + +def get_flash_info(ip): + out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL, seq(), 0, 0, "") + in_pkt = send_and_recv(out_pkt, ip) + + (proto_ver, pktid, rxseq, sector_size_bytes, memory_size_bytes) = unpack_flash_info_fmt(in_pkt) + + if pktid != update_id_t.USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG: + raise Exception, "Invalid reply %c from device." % (chr(pktid)) + + + return (memory_size_bytes, sector_size_bytes) + +def burn_fw(ip, fw, fpga): + init_update(ip) + (flash_size, sector_size) = get_flash_info(ip) + + print "Flash size: %i\nSector size: %i" % (flash_size, sector_size) + + if fpga: + fpga_file = open(fpga, 'rb') + fpga_image = fpga_file.read() + erase_image(ip, SAFE_FPGA_IMAGE_LOCATION_ADDR, FPGA_IMAGE_SIZE_BYTES) + write_image(ip, fpga_image, SAFE_FPGA_IMAGE_LOCATION_ADDR) #TODO: DO NOT WRITE SAFE IMAGE! this is only here because the bootloader isn't finished yet + verify_image(ip, fpga_image, SAFE_FPGA_IMAGE_LOCATION_ADDR) + + if fw: + fw_file = open(fw, 'rb') + fw_image = fw_file.read() + erase_image(ip, PROD_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES) + write_image(ip, fw_image, PROD_FW_IMAGE_LOCATION_ADDR) + verify_image(ip, fw_image, PROD_FW_IMAGE_LOCATION_ADDR) + +def write_image(ip, image, addr): +#we split the image into smaller (256B) bits and send them down the wire + while image: + out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL, seq(), addr, FLASH_DATA_PACKET_SIZE, image[:FLASH_DATA_PACKET_SIZE]) + in_pkt = send_and_recv(out_pkt, ip) + + (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt) + + if pktid != update_id_t.USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG: + raise Exception, "Invalid reply %c from device." % (chr(pktid)) + + image = image[FLASH_DATA_PACKET_SIZE:] + addr += FLASH_DATA_PACKET_SIZE + +def verify_image(ip, image, addr): + readsize = len(image) + readdata = str() + while readsize > 0: + if readsize < FLASH_DATA_PACKET_SIZE: thisreadsize = readsize + else: thisreadsize = FLASH_DATA_PACKET_SIZE + out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL, seq(), addr, thisreadsize, "") + in_pkt = send_and_recv(out_pkt, ip) + + (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt) + + if pktid != update_id_t.USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG: + raise Exception, "Invalid reply %c from device." % (chr(pktid)) + + readdata += data[:thisreadsize] + readsize -= FLASH_DATA_PACKET_SIZE + addr += FLASH_DATA_PACKET_SIZE + + print "Read back %i bytes" % len(readdata) + print readdata + +# for i in range(256, 512): +# print "out: %i in: %i" % (ord(image[i]), ord(readdata[i])) + + if readdata != image: + print "Verify failed. Image did not write correctly." + else: + print "Success." + +def erase_image(ip, addr, length): + #get flash info first + out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL, seq(), addr, length, "") + in_pkt = send_and_recv(out_pkt, ip) + + (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt) + + if pktid != update_id_t.USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG: + raise Exception, "Invalid reply %c from device." % (chr(pktid)) + + print "Erasing %i bytes at %i" % (length, addr) + + #now wait for it to finish + while(1): + out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL, seq(), 0, 0, "") + in_pkt = send_and_recv(out_pkt, ip) + + (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt) + + if pktid == update_id_t.USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG: break + elif pktid != update_id_t.USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG: + raise Exception, "Invalid reply %c from device." % (chr(pktid)) + + print "\tFinished." + +#def verify_image(ip, image, addr): + + +######################################################################## +# command line options +######################################################################## +def get_options(): + parser = optparse.OptionParser() + parser.add_option("--ip", type="string", help="USRP2P firmware address", default='') + parser.add_option("--fw", type="string", help="firmware image path (optional)", default='') + parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='') + (options, args) = parser.parse_args() + + return options + +######################################################################## +# main +######################################################################## +if __name__=='__main__': + options = get_options() + if not options.ip: raise Exception, 'no ip address specified' + + if not options.fpga and not options.fw: raise Exception, 'Must specify either a firmware image or FPGA image.' + burn_fw(ip=options.ip, fw=options.fw, fpga=options.fpga) -- cgit v1.2.3 From 42547a0be8e52758d340fd1eba51a2dd5274a652 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 18 Aug 2010 14:38:50 -0700 Subject: Moved UDP firmware update stuff out of fw_common.h into udp_fw_update.h. This stuff should only go back into fw_common.h if we decide to integrate firmware update into the UHD code. Right now it's a separate Python script. Also moved udp_fw_update.h to lib/ because it's the same between USRP2 and USRP2P. --- firmware/microblaze/Makefile.common | 9 +++- firmware/microblaze/lib/udp_fw_update.h | 71 ++++++++++++++++++++++++++++++ firmware/microblaze/usrp2/udp_fw_update.c | 4 +- firmware/microblaze/usrp2/udp_fw_update.h | 22 --------- firmware/microblaze/usrp2p/Makefile.am | 2 +- firmware/microblaze/usrp2p/udp_fw_update.c | 20 +++------ firmware/microblaze/usrp2p/udp_fw_update.h | 22 --------- host/lib/usrp/usrp2/fw_common.h | 48 -------------------- host/utils/usrp2p_fw_update.py | 2 +- 9 files changed, 87 insertions(+), 113 deletions(-) create mode 100644 firmware/microblaze/lib/udp_fw_update.h delete mode 100644 firmware/microblaze/usrp2/udp_fw_update.h delete mode 100644 firmware/microblaze/usrp2p/udp_fw_update.h (limited to 'firmware') diff --git a/firmware/microblaze/Makefile.common b/firmware/microblaze/Makefile.common index ceb6a553a..4e726edab 100644 --- a/firmware/microblaze/Makefile.common +++ b/firmware/microblaze/Makefile.common @@ -59,8 +59,13 @@ COMMON_LFLAGS = \ ######################################################################## # Common stuff for building top level microblaze images ######################################################################## +#we use COMMON_IHX_ARGS to relocate the reset and interrupt vectors to +#just below the start of code. upon creating the BIN, any leading padding +#is thrown out, so the .bin file is valid for uploading to USRP2P. this +#does not affect USRP2 because the USRP2 already starts at 0x0000, and +#because the relocate_args are not defined for USRP2's Makefile.am. .elf.bin: - $(MB_OBJCOPY) -O binary $< $@ + $(MB_OBJCOPY) -O binary $(RELOCATE_ARGS) $< $@ .elf.dump: $(MB_OBJDUMP) -DSC $< > $@ @@ -69,7 +74,7 @@ COMMON_LFLAGS = \ $(HEXDUMP) -v -e'1/1 "%.2X\n"' $< > $@ .elf.ihx: - $(MB_OBJCOPY) -O ihex $(COMMON_IHX_ARGS) $< $@ + $(MB_OBJCOPY) -O ihex $(RELOCATE_ARGS) $< $@ _generated_from_elf = \ $(noinst_PROGRAMS:.elf=.map) \ diff --git a/firmware/microblaze/lib/udp_fw_update.h b/firmware/microblaze/lib/udp_fw_update.h new file mode 100644 index 000000000..d25525bd2 --- /dev/null +++ b/firmware/microblaze/lib/udp_fw_update.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * 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 "net_common.h" + +#define USRP2_UDP_UPDATE_PORT 49154 + +typedef enum { + USRP2_FW_UPDATE_ID_WAT = ' ', + + USRP2_FW_UPDATE_ID_OHAI_LOL = 'a', + USRP2_FW_UPDATE_ID_OHAI_OMG = 'A', + + USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL = 'f', + USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG = 'F', + + USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL = 'e', + USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG = 'E', + + USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL = 'd', + USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG = 'D', + USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG = 'B', + + USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL = 'w', + USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG = 'W', + + USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL = 'r', + USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG = 'R', + + USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL = 's', + USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG = 'S', + + USRP2_FW_UPDATE_ID_KTHXBAI = '~' + +} usrp2_fw_update_id_t; + +typedef struct { + uint32_t proto_ver; + uint32_t id; + uint32_t seq; + union { + uint32_t ip_addr; + struct { + uint32_t flash_addr; + uint32_t length; + uint8_t data[256]; + } flash_args; + struct { + uint32_t sector_size_bytes; + uint32_t memory_size_bytes; + } flash_info_args; + } data; +} usrp2_fw_update_data_t; + +void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, + unsigned char *payload, int payload_len); diff --git a/firmware/microblaze/usrp2/udp_fw_update.c b/firmware/microblaze/usrp2/udp_fw_update.c index bd62aed85..14eb0b1ee 100644 --- a/firmware/microblaze/usrp2/udp_fw_update.c +++ b/firmware/microblaze/usrp2/udp_fw_update.c @@ -20,14 +20,14 @@ #include "net_common.h" #include "usrp2/fw_common.h" -#include "udp_fw_update.h" #include +#include "udp_fw_update.h" //Firmware update packet handler void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len) { - udp_fw_update_data_t update_data_out; + usrp2_fw_update_data_t update_data_out; update_data_out.id = USRP2_FW_UPDATE_ID_WAT; send_udp_pkt(USRP2_UDP_UPDATE_PORT, src, &update_data_out, sizeof(update_data_out)); diff --git a/firmware/microblaze/usrp2/udp_fw_update.h b/firmware/microblaze/usrp2/udp_fw_update.h deleted file mode 100644 index dcf44bc42..000000000 --- a/firmware/microblaze/usrp2/udp_fw_update.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- c++ -*- */ -/* - * 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 "net_common.h" - -void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, - unsigned char *payload, int payload_len); diff --git a/firmware/microblaze/usrp2p/Makefile.am b/firmware/microblaze/usrp2p/Makefile.am index c9ed3b99b..e6bff2dbc 100644 --- a/firmware/microblaze/usrp2p/Makefile.am +++ b/firmware/microblaze/usrp2p/Makefile.am @@ -27,7 +27,7 @@ AM_LDFLAGS = \ -Wl,-defsym -Wl,_STACK_SIZE=3072 #all of this here is to relocate the hardware vectors to somewhere normal. -COMMON_IHX_ARGS = \ +RELOCATE_ARGS = \ --change-section-address .vectors.sw_exception+0x8000 \ --change-section-address .vectors.hw_exception+0x8000 \ --change-section-address .vectors.interrupt+0x8000 \ diff --git a/firmware/microblaze/usrp2p/udp_fw_update.c b/firmware/microblaze/usrp2p/udp_fw_update.c index 6b860007a..9242242e7 100644 --- a/firmware/microblaze/usrp2p/udp_fw_update.c +++ b/firmware/microblaze/usrp2p/udp_fw_update.c @@ -22,28 +22,18 @@ #include "usrp2/fw_common.h" #include "spi.h" #include "spi_flash.h" -#include "udp_fw_update.h" #include #include #include "ethernet.h" +#include "udp_fw_update.h" //Firmware update packet handler void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len) { -//okay, we can do this ANY NUMBER of ways. we have up to ~1500 bytes to play with -- we don't handle -//fragmentation, so limit it to id; //ensure that the protocol versions match @@ -55,9 +45,9 @@ void handle_udp_fw_update_packet(struct socket_address src, struct socket_addres } //ensure that this is not a short packet - if (payload_len < sizeof(udp_fw_update_data_t)){ + if (payload_len < sizeof(usrp2_fw_update_data_t)){ printf("!Error in update packet handler: Expected payload length %d, but got %d\n", - (int)sizeof(udp_fw_update_data_t), payload_len + (int)sizeof(usrp2_fw_update_data_t), payload_len ); update_data_in_id = USRP2_FW_UPDATE_ID_WAT; } diff --git a/firmware/microblaze/usrp2p/udp_fw_update.h b/firmware/microblaze/usrp2p/udp_fw_update.h deleted file mode 100644 index dcf44bc42..000000000 --- a/firmware/microblaze/usrp2p/udp_fw_update.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- c++ -*- */ -/* - * 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 "net_common.h" - -void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, - unsigned char *payload, int payload_len); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 320ed7d77..4d3b62d6b 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -43,7 +43,6 @@ extern "C" { // Dynamic and/or private ports: 49152-65535 #define USRP2_UDP_CTRL_PORT 49152 #define USRP2_UDP_DATA_PORT 49153 -#define USRP2_UDP_UPDATE_PORT 49154 //for firmware upgrade commands //////////////////////////////////////////////////////////////////////// // I2C addresses @@ -94,35 +93,6 @@ typedef enum{ } usrp2_ctrl_id_t; -typedef enum { - USRP2_FW_UPDATE_ID_WAT = ' ', - - USRP2_FW_UPDATE_ID_OHAI_LOL = 'a', - USRP2_FW_UPDATE_ID_OHAI_OMG = 'A', - - USRP2_FW_UPDATE_ID_WATS_TEH_FLASH_INFO_LOL = 'f', - USRP2_FW_UPDATE_ID_HERES_TEH_FLASH_INFO_OMG = 'F', - - USRP2_FW_UPDATE_ID_ERASE_TEH_FLASHES_LOL = 'e', - USRP2_FW_UPDATE_ID_ERASING_TEH_FLASHES_OMG = 'E', - - USRP2_FW_UPDATE_ID_R_U_DONE_ERASING_LOL = 'd', - USRP2_FW_UPDATE_ID_IM_DONE_ERASING_OMG = 'D', - USRP2_FW_UPDATE_ID_NOPE_NOT_DONE_ERASING_OMG = 'B', - - USRP2_FW_UPDATE_ID_WRITE_TEH_FLASHES_LOL = 'w', - USRP2_FW_UPDATE_ID_WROTE_TEH_FLASHES_OMG = 'W', - - USRP2_FW_UPDATE_ID_READ_TEH_FLASHES_LOL = 'r', - USRP2_FW_UPDATE_ID_KK_READ_TEH_FLASHES_OMG = 'R', - - USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL = 's', - USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG = 'S', - - USRP2_FW_UPDATE_ID_KTHXBAI = '~' - -} usrp2_fw_update_id_t; - typedef enum{ USRP2_DIR_RX = 'r', USRP2_DIR_TX = 't' @@ -167,24 +137,6 @@ typedef struct{ } data; } usrp2_ctrl_data_t; -typedef struct { - __stdint(uint32_t) proto_ver; - __stdint(uint32_t) id; - __stdint(uint32_t) seq; - union { - __stdint(uint32_t) ip_addr; - struct { - __stdint(uint32_t) flash_addr; - __stdint(uint32_t) length; - __stdint(uint8_t) data[256]; - } flash_args; - struct { - __stdint(uint32_t) sector_size_bytes; - __stdint(uint32_t) memory_size_bytes; - } flash_info_args; - } data; -} udp_fw_update_data_t; - #undef __stdint #ifdef __cplusplus } diff --git a/host/utils/usrp2p_fw_update.py b/host/utils/usrp2p_fw_update.py index b15542933..5eff83c07 100755 --- a/host/utils/usrp2p_fw_update.py +++ b/host/utils/usrp2p_fw_update.py @@ -36,7 +36,7 @@ UDP_MAX_XFER_BYTES = 1024 UDP_TIMEOUT = 3 UDP_POLL_INTERVAL = 0.10 #in seconds -USRP2_FW_PROTO_VERSION = 5 +USRP2_FW_PROTO_VERSION = 6 #from bootloader_utils.h PROD_FPGA_IMAGE_LOCATION_ADDR = 0x00200000 -- cgit v1.2.3 From 0019bb05437702a6727d3632c6efc6a600bb4aa2 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 25 Aug 2010 18:55:09 -0700 Subject: Change to get codec_impl to compile, dur. Changed memory map to correspond to new tx_policy code. --- firmware/microblaze/usrp2p/memory_map.h | 4 ++-- host/lib/usrp/usrp2/codec_impl.cpp | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h index addcf67d4..8d0d0c365 100644 --- a/firmware/microblaze/usrp2p/memory_map.h +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -417,12 +417,12 @@ typedef struct { // crazy order that matches the labels on the case #define LED_A (1 << 2) -#define LED_B (1 << 5) +#define LED_B (1 << 0) #define LED_E (1 << 3) #define LED_D (1 << 1) #define LED_C (1 << 4) // LED_F // controlled by CPLD -#define LED_RJ45 (1 << 0) +#define LED_RJ45 (1 << 5) #define output_regs ((output_regs_t *) MISC_OUTPUT_BASE) diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp index f7f9ce2d5..db98e50ab 100644 --- a/host/lib/usrp/usrp2/codec_impl.cpp +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -53,7 +53,8 @@ void usrp2_mboard_impl::codec_init(void){ /*********************************************************************** * RX Codec Properties **********************************************************************/ -void usrp2_mboard_impl::rx_codec_get(const wax::obj &key, wax::obj &val){ +void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ @@ -73,23 +74,21 @@ void usrp2_mboard_impl::rx_codec_get(const wax::obj &key, wax::obj &val){ case CODEC_PROP_GAIN_I: case CODEC_PROP_GAIN_Q: - assert_has(_codec_rx_gains.keys(), name, "codec rx gain name"); - val = _codec_rx_gains[name]; + assert_has(_codec_rx_gains.keys(), key.name, "codec rx gain name"); + val = _codec_rx_gains[key.name]; return; case CODEC_PROP_GAIN_RANGE: - assert_has(codec_rx_gain_ranges.keys(), name, "codec rx gain range name"); - val = codec_rx_gain_ranges[name]; - return; + assert_has(codec_rx_gain_ranges.keys(), key.name, "codec rx gain range name"); + val = codec_rx_gain_ranges[key.name]; + return; default: UHD_THROW_PROP_GET_ERROR(); } } void usrp2_mboard_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ - wax::obj key; std::string name; - boost::tie(key, name) = extract_named_prop(key_); - + named_prop_t key = named_prop_t::extract(key_); float gain; switch(key.as()) { @@ -98,7 +97,7 @@ void usrp2_mboard_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ if(_iface->get_hw_rev() < USRP2P_FIRST_HW_REV) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P gain = val.as(); - this->rx_codec_set_gain(gain, name); + this->rx_codec_set_gain(gain, key.name); return; default: @@ -134,7 +133,8 @@ void usrp2_mboard_impl::rx_codec_set_gain(float gain, const std::string &name){ /*********************************************************************** * TX Codec Properties **********************************************************************/ -void usrp2_mboard_impl::tx_codec_get(const wax::obj &key, wax::obj &val){ +void usrp2_mboard_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); //handle the get request conditioned on the key switch(key.as()){ -- cgit v1.2.3 From 92fdf6ab255cc07091bbdb59e7eb5e57553115ba Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 5 Oct 2010 11:53:43 -0700 Subject: U2P: 32/64Mbit FLASH support, internal reference support for U2P r2 --- firmware/microblaze/usrp2p/bootloader_utils.h | 9 +++++---- host/lib/ic_reg_maps/CMakeLists.txt | 6 +++--- host/lib/usrp/usrp2/mboard_impl.cpp | 20 +++++++++++++++----- host/utils/usrp2p_fw_update.py | 13 +++++++------ 4 files changed, 30 insertions(+), 18 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/usrp2p/bootloader_utils.h b/firmware/microblaze/usrp2p/bootloader_utils.h index c72128f43..f597c0113 100644 --- a/firmware/microblaze/usrp2p/bootloader_utils.h +++ b/firmware/microblaze/usrp2p/bootloader_utils.h @@ -7,14 +7,15 @@ #include //we're working in bytes and byte addresses so we can run the same code with Flash chips of different sector sizes. -#define FPGA_IMAGE_SIZE_BYTES 2097152 +//it's really 1463736, but rounded up to 1.5MB +#define FPGA_IMAGE_SIZE_BYTES 1572864 //instead of 32K, we write 31K because we're using the top 1K for stack space! #define FW_IMAGE_SIZE_BYTES 31744 #define SAFE_FPGA_IMAGE_LOCATION_ADDR 0x00000000 -#define SAFE_FW_IMAGE_LOCATION_ADDR 0x007F0000 -#define PROD_FPGA_IMAGE_LOCATION_ADDR 0x00200000 -#define PROD_FW_IMAGE_LOCATION_ADDR 0x00400000 +#define SAFE_FW_IMAGE_LOCATION_ADDR 0x003F0000 +#define PROD_FPGA_IMAGE_LOCATION_ADDR 0x00180000 +#define PROD_FW_IMAGE_LOCATION_ADDR 0x00300000 int is_valid_fpga_image(uint32_t addr); int is_valid_fw_image(uint32_t addr); diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt index 507f214c9..772166334 100644 --- a/host/lib/ic_reg_maps/CMakeLists.txt +++ b/host/lib/ic_reg_maps/CMakeLists.txt @@ -70,11 +70,11 @@ LIBUHD_PYTHON_GEN_SOURCE( ) LIBUHD_PYTHON_GEN_SOURCE( -<<<<<<< HEAD ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_ads62p44_regs.py ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/ads62p44_regs.hpp -======= + ) + +LIBUHD_PYTHON_GEN_SOURCE( ${CMAKE_SOURCE_DIR}/lib/ic_reg_maps/gen_tuner_4937di5_regs.py ${CMAKE_BINARY_DIR}/lib/ic_reg_maps/tuner_4937di5_regs.hpp ->>>>>>> bd3bd0dfbc1a87af5839c9b23450434cfb9c763c ) diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 2669df9bc..3ae21e621 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -160,11 +160,21 @@ void usrp2_mboard_impl::update_clock_config(void){ _iface->poke32(_iface->regs.time64_flags, pps_flags); //clock source ref 10mhz - switch(_clock_config.ref_source){ - case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break; - case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; - case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; - default: throw std::runtime_error("usrp2: unhandled clock configuration reference source"); + if(_iface->get_hw_rev() >= USRP2P_FIRST_HW_REV) { + switch(_clock_config.ref_source){ + case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break; + case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; + case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; + default: throw std::runtime_error("usrp2: unhandled clock configuration reference source"); + } + } else { + + switch(_clock_config.ref_source){ + case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break; + case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; + case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; + default: throw std::runtime_error("usrp2: unhandled clock configuration reference source"); + } } //clock source ref 10mhz diff --git a/host/utils/usrp2p_fw_update.py b/host/utils/usrp2p_fw_update.py index 5eff83c07..ed3465c0e 100755 --- a/host/utils/usrp2p_fw_update.py +++ b/host/utils/usrp2p_fw_update.py @@ -39,12 +39,13 @@ UDP_POLL_INTERVAL = 0.10 #in seconds USRP2_FW_PROTO_VERSION = 6 #from bootloader_utils.h -PROD_FPGA_IMAGE_LOCATION_ADDR = 0x00200000 -PROD_FW_IMAGE_LOCATION_ADDR = 0x00400000 -SAFE_FW_IMAGE_LOCATION_ADDR = 0x007F0000 -SAFE_FPGA_IMAGE_LOCATION_ADDR = 0x00000000 -FPGA_IMAGE_SIZE_BYTES = 2097152 -FW_IMAGE_SIZE_BYTES = 31744 + +#define FPGA_IMAGE_SIZE_BYTES 1572864 +#define FW_IMAGE_SIZE_BYTES 31744 +#define SAFE_FPGA_IMAGE_LOCATION_ADDR 0x00000000 +#define SAFE_FW_IMAGE_LOCATION_ADDR 0x003F0000 +#define PROD_FPGA_IMAGE_LOCATION_ADDR 0x00180000 +#define PROD_FW_IMAGE_LOCATION_ADDR 0x00300000 FLASH_DATA_PACKET_SIZE = 256 -- cgit v1.2.3 From c205cd329b37f24060ff20c23bc91249969502a1 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 7 Oct 2010 18:09:53 -0700 Subject: U2P: Bootloader/ICAP updates. 2-stage bootloader works. Uses EEPROM for state info. --- firmware/microblaze/lib/xilinx_s3_icap.c | 101 --------------------- firmware/microblaze/usrp2p/Makefile.am | 1 + firmware/microblaze/usrp2p/bootloader/Makefile.am | 2 +- .../microblaze/usrp2p/bootloader/init_bootloader.c | 53 ++++++++--- firmware/microblaze/usrp2p/bootloader_utils.c | 18 ++-- firmware/microblaze/usrp2p/udp_fw_update.c | 2 + firmware/microblaze/usrp2p/xilinx_s3_icap.c | 99 ++++++++++++++++++++ host/utils/usrp2p_fw_update.py | 59 +++++++++--- 8 files changed, 197 insertions(+), 138 deletions(-) delete mode 100644 firmware/microblaze/lib/xilinx_s3_icap.c create mode 100644 firmware/microblaze/usrp2p/xilinx_s3_icap.c (limited to 'firmware') diff --git a/firmware/microblaze/lib/xilinx_s3_icap.c b/firmware/microblaze/lib/xilinx_s3_icap.c deleted file mode 100644 index 8aa7fd297..000000000 --- a/firmware/microblaze/lib/xilinx_s3_icap.c +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- c -*- */ -/* - * Copyright 2009 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 . - */ - - -/* Changes required to work for the Spartan-3A series: - * The ICAP interface on the 3A is 8 bits wide, instead of 32. - * Everything is Xilinx standard LSB-first. - * The operations are all different. - * Commands are 16 bits long, presented to the ICAP interface 8 bits at a time. -*/ - -#include -#include -#include //for READ_CMD - - -/* bit swap end-for-end */ -static unsigned char -swap8(unsigned char x) -{ - unsigned char r = 0; - r |= (x >> 7) & 0x01; - r |= (x >> 5) & 0x02; - r |= (x >> 3) & 0x04; - r |= (x >> 1) & 0x08; - - r |= (x << 1) & 0x10; - r |= (x << 3) & 0x20; - r |= (x << 5) & 0x40; - r |= (x << 7) & 0x80; - - return r; -} - -void -wr_icap(uint8_t x) -{ - uint8_t t = swap8(x); - - icap_regs->icap = t; //DEBUG: does not swap bits -} - -uint8_t -rd_icap(void) -{ - return swap8(icap_regs->icap); -} - - -void -icap_reload_fpga(uint32_t flash_address) -//this DOES NOT WORK right now. reboot is not getting executed correctly. -{ - union { - uint32_t i; - uint8_t c[4]; - } t; - t.i = flash_address; - - //note! t.c[0] MUST contain the byte-wide read command for the flash device used. - //for the 25P64, and most other flash devices, this is 0x03. - t.c[0] = READ_CMD; //legacy command, use FAST_READ_CMD 0x0B after testing - - //TODO: look up the watchdog timer, ensure it won't fire too soon - - //UG332 p279 -// wr_icap(0xff); -// wr_icap(0xff); //dummy word, probably unnecessary - wr_icap(0xAA); - wr_icap(0x99); //sync word - wr_icap(0x32); - wr_icap(0x61); //Type 1 write General 1 (1 word) - wr_icap(t.c[2]); //bits 15-8 - wr_icap(t.c[3]); //bits 7-0 - wr_icap(0x32); - wr_icap(0x81); //Type 1 write General 2 (1 word) - wr_icap(t.c[0]); //C0-C8, the byte-wide read command - wr_icap(t.c[1]); //Upper 8 bits of 24-bit address - wr_icap(0x30); - wr_icap(0xA1); //Type 1 write CMD (1 word) - wr_icap(0x00); - wr_icap(0x0E); //REBOOT command - wr_icap(0x20); - wr_icap(0x00); //Type 1 NOP - -} diff --git a/firmware/microblaze/usrp2p/Makefile.am b/firmware/microblaze/usrp2p/Makefile.am index e6bff2dbc..0d0b60437 100644 --- a/firmware/microblaze/usrp2p/Makefile.am +++ b/firmware/microblaze/usrp2p/Makefile.am @@ -51,6 +51,7 @@ libusrp2p_a_SOURCES = \ spi_flash_read.c \ bootloader_utils.c \ ethernet.c \ + xilinx_s3_icap.c \ udp_fw_update.c noinst_PROGRAMS = \ diff --git a/firmware/microblaze/usrp2p/bootloader/Makefile.am b/firmware/microblaze/usrp2p/bootloader/Makefile.am index 1fc5daf9c..eb72d937d 100644 --- a/firmware/microblaze/usrp2p/bootloader/Makefile.am +++ b/firmware/microblaze/usrp2p/bootloader/Makefile.am @@ -30,7 +30,7 @@ LDADD = $(top_srcdir)/usrp2p/libusrp2p.a noinst_PROGRAMS = \ init_bootloader.elf -init_bootloader_elf_SOURCES = init_bootloader.c +init_bootloader_elf_SOURCES = init_bootloader.c i2c_sync.c .bin.rmi: $(top_srcdir)/bin/bin_to_ram_macro_init.py $< $@ diff --git a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c index 15d719d73..8b513002d 100644 --- a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c +++ b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c @@ -15,6 +15,12 @@ #include #include #include +#include "i2c_sync.h" + +#define SAFE_FLAG_LOCATION 247 + +bool find_safe_booted_flag(void); +void set_safe_booted_flag(bool flag); void pic_interrupt_handler() __attribute__ ((interrupt_handler)); @@ -23,6 +29,19 @@ void pic_interrupt_handler() // nop stub } +bool find_safe_booted_flag(void) { + unsigned char flag_byte; + i2c_read(SAFE_FLAG_LOCATION, &flag_byte, 1); + + return (flag_byte != 0x5E); +} + +void set_safe_booted_flag(bool flag) { + unsigned char flag_byte = flag ? 0x5E : 0xDC; + i2c_write(SAFE_FLAG_LOCATION, &flag_byte, 1); +} + + void load_ihex(void) { //simple IHEX parser to load proper records into RAM. loads program when it receives end of record. char buf[128]; //input data buffer uint8_t ihx[32]; //ihex data buffer @@ -51,19 +70,18 @@ void delay(uint32_t t) { while(t-- != 0) asm("NOP"); } -//let's clean up this logic. state machine? no, you only have to go through it once. - -//don't need else cases since all these are terminal cases - int main(int argc, char *argv[]) { hal_disable_ints(); // In case we got here via jmp 0x0 output_regs->leds = 0xFF; delay(500000); output_regs->leds = 0x00; - hal_uart_init(); + hal_uart_init(); spif_init(); -// i2c_init(); //for EEPROM + i2c_init(); //for EEPROM puts("USRP2+ bootloader\n"); + + bool production_image = find_safe_booted_flag(); + if(production_image) set_safe_booted_flag(0); //we're the production image, so we clear the flag for the next boot if(BUTTON_PUSHED) { //see memory_map.h puts("Starting USRP2+ in safe mode."); @@ -71,26 +89,31 @@ int main(int argc, char *argv[]) { spi_flash_read(SAFE_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE); start_program(RAM_BASE); puts("ERROR: return from main program! This should never happen!"); - //icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); } else { puts("ERROR: no safe firmware image available. I am a brick. Feel free to load IHEX to RAM."); + //puts("ERROR: no safe firmware image available. I am a brick."); load_ihex(); } } - puts("Checking for valid production FPGA image..."); - if(is_valid_fpga_image(PROD_FPGA_IMAGE_LOCATION_ADDR)) { - puts("Valid production FPGA image found. Attempting to boot."); - //icap_reload_fpga(PROD_FPGA_IMAGE_LOCATION_ADDR); + if(!production_image) { + puts("Checking for valid production FPGA image..."); + if(is_valid_fpga_image(PROD_FPGA_IMAGE_LOCATION_ADDR)) { + puts("Valid production FPGA image found. Attempting to boot."); + set_safe_booted_flag(1); + delay(10000); + icap_reload_fpga(PROD_FPGA_IMAGE_LOCATION_ADDR); + } + puts("No valid production FPGA image found.\nAttempting to load production firmware..."); } - puts("No valid production FPGA image found.\nAttempting to load production firmware..."); if(is_valid_fw_image(PROD_FW_IMAGE_LOCATION_ADDR)) { puts("Valid production firmware found. Loading..."); spi_flash_read(PROD_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE); start_program(RAM_BASE); puts("ERROR: Return from main program! This should never happen!"); //if this happens, though, the safest thing to do is reboot the whole FPGA and start over. - //icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); return 1; } puts("No valid production firmware found. Trying safe firmware..."); @@ -98,8 +121,8 @@ int main(int argc, char *argv[]) { spi_flash_read(SAFE_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE); start_program(RAM_BASE); puts("ERROR: return from main program! This should never happen!"); - //icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); - return 1; //_exit will trap in loop + icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + return 1; } puts("ERROR: no safe firmware image available. I am a brick. Feel free to load IHEX to RAM."); load_ihex(); diff --git a/firmware/microblaze/usrp2p/bootloader_utils.c b/firmware/microblaze/usrp2p/bootloader_utils.c index 00893db02..fadd225bb 100644 --- a/firmware/microblaze/usrp2p/bootloader_utils.c +++ b/firmware/microblaze/usrp2p/bootloader_utils.c @@ -5,16 +5,23 @@ */ //contains routines for loading programs from Flash. depends on Flash libraries. +//also contains routines for reading / writing EEPROM flags for the bootloader +#include #include #include #include - int is_valid_fpga_image(uint32_t addr) { - static const uint8_t fpgaheader[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x99}; //AA 99 is the standard Xilinx sync sequence, and it's always prefixed with 0xFF padding - uint8_t buf[10]; - spi_flash_read(addr, 6, buf); - return memcmp(buf, fpgaheader, 6) == 0; + uint8_t imgbuf[64]; + spi_flash_read(addr, 64, imgbuf); + //we're just looking for leading 0xFF padding, followed by the sync bytes 0xAA 0x99 + int i = 0; + for(i; i<63; i++) { + if(imgbuf[i] == 0xFF) continue; + if(imgbuf[i] == 0xAA && imgbuf[i+1] == 0x99) return 1; + } + + return 0; } int is_valid_fw_image(uint32_t addr) { @@ -30,4 +37,3 @@ void start_program(uint32_t addr) typedef void (*fptr_t)(void); (*(fptr_t) 0x00000000)(); // most likely no return } - diff --git a/firmware/microblaze/usrp2p/udp_fw_update.c b/firmware/microblaze/usrp2p/udp_fw_update.c index 9242242e7..55c206b1b 100644 --- a/firmware/microblaze/usrp2p/udp_fw_update.c +++ b/firmware/microblaze/usrp2p/udp_fw_update.c @@ -26,6 +26,7 @@ #include #include "ethernet.h" #include "udp_fw_update.h" +#include "xilinx_s3_icap.h" //Firmware update packet handler void handle_udp_fw_update_packet(struct socket_address src, struct socket_address dst, @@ -94,6 +95,7 @@ void handle_udp_fw_update_packet(struct socket_address src, struct socket_addres //should reset via icap_reload_fpga(uint32_t flash_address); update_data_out.id = USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG; //you should note that if you get a reply packet to this the reset has obviously failed + icap_reload_fpga(0); break; // case USRP2_FW_UPDATE_ID_KTHXBAI: //see ya diff --git a/firmware/microblaze/usrp2p/xilinx_s3_icap.c b/firmware/microblaze/usrp2p/xilinx_s3_icap.c new file mode 100644 index 000000000..50c85231c --- /dev/null +++ b/firmware/microblaze/usrp2p/xilinx_s3_icap.c @@ -0,0 +1,99 @@ +/* -*- c -*- */ +/* + * Copyright 2009 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 . + */ + + +/* Changes required to work for the Spartan-3A series: + * The ICAP interface on the 3A is 8 bits wide, instead of 32. + * Everything is Xilinx standard LSBit-first. + * The operations are all different. + * Commands are 16 bits long, presented to the ICAP interface 8 bits at a time. +*/ + +#include +#include +#include //for READ_CMD + + +/* bit swap end-for-end */ +static inline unsigned char +swap8(unsigned char x) +{ + unsigned char r = 0; + r |= (x >> 7) & 0x01; + r |= (x >> 5) & 0x02; + r |= (x >> 3) & 0x04; + r |= (x >> 1) & 0x08; + + r |= (x << 1) & 0x10; + r |= (x << 3) & 0x20; + r |= (x << 5) & 0x40; + r |= (x << 7) & 0x80; + + return r; +} + +void +wr_icap(uint8_t x) +{ + icap_regs->icap = swap8(x); +} + +uint8_t +rd_icap(void) +{ + return swap8(icap_regs->icap); +} + + +void +icap_reload_fpga(uint32_t flash_address) +{ + union { + uint32_t i; + uint8_t c[4]; + } t; + t.i = flash_address; + + //note! t.c[0] MUST contain the byte-wide read command for the flash device used. + //for the 25P64, and most other flash devices, this is 0x03. + t.c[0] = FAST_READ_CMD; + + //TODO: look up the watchdog timer, ensure it won't fire too soon + + //UG332 p279 + wr_icap(0xff); + wr_icap(0xff); //dummy word, probably unnecessary + wr_icap(0xAA); + wr_icap(0x99); //sync word + wr_icap(0x32); + wr_icap(0x61); //Type 1 write General 1 (1 word) + wr_icap(t.c[2]); //bits 15-8 + wr_icap(t.c[3]); //bits 7-0 + wr_icap(0x32); + wr_icap(0x81); //Type 1 write General 2 (1 word) + wr_icap(t.c[0]); //C0-C8, the byte-wide read command + wr_icap(t.c[1]); //Upper 8 bits of 24-bit address + wr_icap(0x30); + wr_icap(0xA1); //Type 1 write CMD (1 word) + wr_icap(0x00); + wr_icap(0x0E); //REBOOT command + wr_icap(0x20); + wr_icap(0x00); //Type 1 NOP + wr_icap(0x20); + wr_icap(0x00); +} diff --git a/host/utils/usrp2p_fw_update.py b/host/utils/usrp2p_fw_update.py index 1cd735796..0c07c398d 100755 --- a/host/utils/usrp2p_fw_update.py +++ b/host/utils/usrp2p_fw_update.py @@ -146,25 +146,38 @@ def get_flash_info(ip): return (memory_size_bytes, sector_size_bytes) -def burn_fw(ip, fw, fpga): +def burn_fw(ip, fw, fpga, reset, safe): init_update(ip) (flash_size, sector_size) = get_flash_info(ip) print "Flash size: %i\nSector size: %i" % (flash_size, sector_size) - if fpga: + if fpga: + if safe: + image_location = SAFE_FPGA_IMAGE_LOCATION_ADDR + else: + image_location = PROD_FPGA_IMAGE_LOCATION_ADDR + fpga_file = open(fpga, 'rb') fpga_image = fpga_file.read() - erase_image(ip, SAFE_FPGA_IMAGE_LOCATION_ADDR, FPGA_IMAGE_SIZE_BYTES) - write_image(ip, fpga_image, SAFE_FPGA_IMAGE_LOCATION_ADDR) #TODO: DO NOT WRITE SAFE IMAGE! this is only here because the bootloader isn't finished yet - verify_image(ip, fpga_image, SAFE_FPGA_IMAGE_LOCATION_ADDR) + erase_image(ip, image_location, FPGA_IMAGE_SIZE_BYTES) + write_image(ip, fpga_image, image_location) + verify_image(ip, fpga_image, image_location) if fw: + if safe: + image_location = SAFE_FW_IMAGE_LOCATION_ADDR + else: + image_location = PROD_FW_IMAGE_LOCATION_ADDR + fw_file = open(fw, 'rb') fw_image = fw_file.read() - erase_image(ip, PROD_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES) - write_image(ip, fw_image, PROD_FW_IMAGE_LOCATION_ADDR) - verify_image(ip, fw_image, PROD_FW_IMAGE_LOCATION_ADDR) + erase_image(ip, image_location, FW_IMAGE_SIZE_BYTES) + write_image(ip, fw_image, image_location) + verify_image(ip, fw_image, image_location) + + if reset: + reset_usrp(ip) def write_image(ip, image, addr): #we split the image into smaller (256B) bits and send them down the wire @@ -208,6 +221,14 @@ def verify_image(ip, image, addr): print "Verify failed. Image did not write correctly." else: print "Success." + +def reset_usrp(ip): + out_pkt = pack_flash_args_fmt(USRP2_FW_PROTO_VERSION, update_id_t.USRP2_FW_UPDATE_ID_RESET_MAH_COMPUTORZ_LOL, seq(), 0, 0, "") + in_pkt = send_and_recv(out_pkt, ip) + + (proto_ver, pktid, rxseq, flash_addr, rxlength, data) = unpack_flash_args_fmt(in_pkt) + if pktid == update_id_t.USRP2_FW_UPDATE_ID_RESETTIN_TEH_COMPUTORZ_OMG: + raise Exception, "Device failed to reset." def erase_image(ip, addr, length): #get flash info first @@ -234,17 +255,17 @@ def erase_image(ip, addr, length): print "\tFinished." -#def verify_image(ip, image, addr): - ######################################################################## # command line options ######################################################################## def get_options(): parser = optparse.OptionParser() - parser.add_option("--ip", type="string", help="USRP2P firmware address", default='') - parser.add_option("--fw", type="string", help="firmware image path (optional)", default='') - parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='') + parser.add_option("--ip", type="string", help="USRP2P firmware address", default='') + parser.add_option("--fw", type="string", help="firmware image path (optional)", default='') + parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='') + parser.add_option("--reset", action="store_true", help="reset the device after writing", default=False) + parser.add_option("--overwrite-safe", action="store_true", help="never ever use this option", default=False) (options, args) = parser.parse_args() return options @@ -256,5 +277,13 @@ if __name__=='__main__': options = get_options() if not options.ip: raise Exception, 'no ip address specified' - if not options.fpga and not options.fw: raise Exception, 'Must specify either a firmware image or FPGA image.' - burn_fw(ip=options.ip, fw=options.fw, fpga=options.fpga) + if not options.fpga and not options.fw and not options.reset: raise Exception, 'Must specify either a firmware image or FPGA image, and/or reset.' + + if options.overwrite_safe: + print("Are you REALLY, REALLY sure you want to overwrite the safe image? This is ALMOST ALWAYS a terrible idea.") + print("If your image is faulty, your USRP2+ will become a brick until reprogrammed via JTAG.") + response = raw_input("""Type "yes" to continue, or anything else to quit: """) + if response != "yes": + sys.exit(0) + + burn_fw(ip=options.ip, fw=options.fw, fpga=options.fpga, reset=options.reset, safe=options.overwrite_safe) -- cgit v1.2.3 From 4ed75835c8c1b7b633223cd7ad11269e84c41701 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Thu, 7 Oct 2010 18:12:51 -0700 Subject: U2P: Whoops. --- firmware/microblaze/usrp2p/bootloader/init_bootloader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'firmware') diff --git a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c index 8b513002d..3571313ff 100644 --- a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c +++ b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c @@ -33,7 +33,7 @@ bool find_safe_booted_flag(void) { unsigned char flag_byte; i2c_read(SAFE_FLAG_LOCATION, &flag_byte, 1); - return (flag_byte != 0x5E); + return (flag_byte == 0x5E); } void set_safe_booted_flag(bool flag) { -- cgit v1.2.3 From 7db726e9b45b972c8fcb0c1dc366919e11256cc1 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 8 Oct 2010 12:50:00 -0700 Subject: U2P: Bootloader works, successfully loads production image. Split I2C into async and sync halves to keep the size of the bootloader small. --- firmware/microblaze/apps/txrx_uhd.c | 1 + firmware/microblaze/lib/Makefile.inc | 1 + firmware/microblaze/lib/i2c.c | 177 +----------------- firmware/microblaze/lib/i2c.h | 21 --- firmware/microblaze/lib/i2c_async.c | 206 +++++++++++++++++++++ firmware/microblaze/lib/i2c_async.h | 50 +++++ firmware/microblaze/lib/u2_init.c | 2 + firmware/microblaze/usrp2p/bootloader/Makefile.am | 2 +- .../microblaze/usrp2p/bootloader/init_bootloader.c | 10 +- host/lib/usrp/usrp2/fw_common.h | 2 + 10 files changed, 270 insertions(+), 202 deletions(-) create mode 100644 firmware/microblaze/lib/i2c_async.c create mode 100644 firmware/microblaze/lib/i2c_async.h (limited to 'firmware') diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 44be2cc9c..482332f7c 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -42,6 +42,7 @@ #include #include "clocks.h" #include "usrp2/fw_common.h" +#include #include #include #include diff --git a/firmware/microblaze/lib/Makefile.inc b/firmware/microblaze/lib/Makefile.inc index ae123f531..349ff2cd0 100644 --- a/firmware/microblaze/lib/Makefile.inc +++ b/firmware/microblaze/lib/Makefile.inc @@ -32,6 +32,7 @@ COMMON_SRCS = \ $(top_srcdir)/lib/hal_io.c \ $(top_srcdir)/lib/hal_uart.c \ $(top_srcdir)/lib/i2c.c \ + $(top_srcdir)/lib/i2c_async.c \ $(top_srcdir)/lib/mdelay.c \ $(top_srcdir)/lib/memcpy_wa.c \ $(top_srcdir)/lib/memset_wa.c \ diff --git a/firmware/microblaze/lib/i2c.c b/firmware/microblaze/lib/i2c.c index 177341267..d230f462c 100644 --- a/firmware/microblaze/lib/i2c.c +++ b/firmware/microblaze/lib/i2c.c @@ -20,7 +20,6 @@ #include "memory_map.h" #include "stdint.h" #include -#include "pic.h" #include "nonstdio.h" #define MAX_WB_DIV 4 // maximum wishbone divisor (from 100 MHz MASTER_CLK) @@ -37,18 +36,6 @@ static uint16_t prescaler_values[MAX_WB_DIV+1] = { PRESCALER(4), // 4: 25 MHz }; -//asynchronous (interrupt-driven) i2c state variables -volatile uint8_t i2c_buf[17]; //tx/rx data transfer buffer -volatile uint8_t *volatile i2c_bufptr = i2c_buf; //ptr to current position -volatile uint8_t i2c_len = 0; //length remaining in current transfer -volatile i2c_state_t i2c_state = I2C_STATE_IDLE; //current I2C transfer state -i2c_dir_t i2c_dir; //I2C transfer direction - -void (*volatile i2c_callback)(void); //function pointer to i2c callback to be called when transaction is complete - -static void i2c_irq_handler(unsigned irq); -inline void i2c_async_err(void); - void i2c_init(void) { @@ -64,8 +51,8 @@ i2c_init(void) i2c_regs->ctrl = I2C_CTRL_EN; //| I2C_CTRL_IE; // enable core - // FIXME interrupt driven? - pic_register_handler(IRQ_I2C, i2c_irq_handler); + //now this is done separately to maintain common code for async and sync + //pic_register_handler(IRQ_I2C, i2c_irq_handler); } static inline void @@ -140,163 +127,3 @@ i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len) return false; } -static void i2c_irq_handler(unsigned irq) { -//i2c state machine. - - //printf("I2C irq handler\n"); - //first let's make sure nothing is f'ed up - //TODO: uncomment this error checking when we have some way to handle errors -// if(((i2c_regs->cmd_status & I2C_ST_RXACK) != 0) && i2c_dir == I2C_DIR_WRITE) { //we got a NACK and we didn't send it -// printf("\tNACK received\n"); -// i2c_async_err(); -// return; -// }// else printf("\tACK received, proceeding\n"); - - if(i2c_regs->cmd_status & I2C_ST_AL) { - printf("\tArbitration lost!\n"); - i2c_async_err(); - return; - } - - if(i2c_regs->cmd_status & I2C_ST_TIP) { - //printf("\tI2C still busy in interrupt\n"); - return; - } - - //now decide what to do - switch(i2c_state) { - - case I2C_STATE_IDLE: - //this is an error. in idle state, we shouldn't be transferring data, and the fact that the IRQ fired is terrible bad. - printf("AAAAAHHHHH INTERRUPT IN THE IDLE STATE AAAHHHHHHHHH\n"); - i2c_async_err(); - break; - - case I2C_STATE_CONTROL_BYTE_SENT: //here we've sent the control byte, and we're either clocking data in or out now, but we haven't received a byte yet. - case I2C_STATE_DATA: //here we're sending/receiving data and if we're receiving there's data in the data reg - - //if(i2c_state == I2C_STATE_DATA) printf("\tI2C in state DATA with dir=%d and len=%d\n", i2c_dir, i2c_len); - //else printf("\tI2C in state CONTROL_BYTE_SENT with dir=%d and len=%d\n", i2c_dir, i2c_len); - - if(i2c_dir == I2C_DIR_READ) { - if(i2c_state == I2C_STATE_DATA) *(i2c_bufptr++) = i2c_regs->data; - //printf("\tRead %x\n", *(i2c_bufptr-1)); - //set up another data byte - if(i2c_len > 1) //only one more byte to transfer - i2c_regs->cmd_status = I2C_CMD_RD; - else - i2c_regs->cmd_status = I2C_CMD_RD | I2C_CMD_NACK | I2C_CMD_STOP; - } - else if(i2c_dir == I2C_DIR_WRITE) { - //write a byte - //printf("\tWriting %x\n", *i2c_bufptr); - i2c_regs->data = *(i2c_bufptr++); - if(i2c_len > 1) - i2c_regs->cmd_status = I2C_CMD_WR; - else { - //printf("\tGenerating STOP\n"); - i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_STOP; - } - }; - i2c_len--; - if(i2c_len == 0) i2c_state = I2C_STATE_LAST_BYTE; - else i2c_state = I2C_STATE_DATA; //takes care of the addr_sent->data transition - break; - - - case I2C_STATE_LAST_BYTE: //here we've already sent the last read request and the last data is waiting for us. - //printf("\tI2C in state LAST BYTE\n"); - - if(i2c_dir == I2C_DIR_READ) { - *(i2c_bufptr++) = i2c_regs->data; - //printf("\tRead %x\n", *(i2c_bufptr-1)); - i2c_state = I2C_STATE_DATA_READY; - } else { - i2c_state = I2C_STATE_IDLE; - } - i2c_regs->ctrl &= ~I2C_CTRL_IE; //disable interrupts until next time - - if(i2c_callback) { - i2c_callback(); //if we registered a callback, call it! - } - - break; - - - default: //terrible things have happened. - break; - } - -} - -void i2c_register_callback(void (*volatile callback)(void)) { - i2c_callback = callback; -} - -inline void i2c_async_err(void) { - i2c_state = I2C_STATE_IDLE; - i2c_regs->ctrl &= ~I2C_CTRL_IE; - printf("I2C error\n"); -//TODO: set an error flag instead of just dropping things on the floor - i2c_regs->cmd_status = I2C_CMD_STOP; -} - -bool i2c_async_read(uint8_t addr, unsigned int len) { - //printf("Starting async read\n"); - if(i2c_state != I2C_STATE_IDLE) return false; //sorry mario but your i2c is in another castle - if(len == 0) return true; //just idiot-proofing - if(len > sizeof(i2c_buf)) return false; - - //disable I2C interrupts and clear pending interrupts on the I2C device - i2c_regs->ctrl &= ~I2C_CTRL_IE; - i2c_regs->cmd_status |= I2C_CMD_IACK; - - i2c_len = len; - i2c_dir = I2C_DIR_READ; - i2c_bufptr = i2c_buf; - //then set up the transfer by issuing the control byte - i2c_regs->ctrl |= I2C_CTRL_IE; - i2c_regs->data = (addr << 1) | 0x01; //7 bit addr and read bit - i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START; //generate start & start writing addr - //update the state so the irq handler knows what's going on - i2c_state = I2C_STATE_CONTROL_BYTE_SENT; - return true; -} - -bool i2c_async_write(uint8_t addr, const uint8_t *buf, unsigned int len) { - //printf("Starting async write\n"); - if(i2c_state != I2C_STATE_IDLE) return false; //sorry mario but your i2c is in another castle - if(len > sizeof(i2c_buf)) return false; - - //disable I2C interrupts and clear pending interrupts on the I2C device - i2c_regs->ctrl &= ~I2C_CTRL_IE; - i2c_regs->cmd_status |= I2C_CMD_IACK; - - //copy the buffer into our own if writing - memcpy((void *)i2c_buf, buf, len); - - i2c_len = len; - i2c_dir = I2C_DIR_WRITE; - i2c_bufptr = i2c_buf; - //then set up the transfer by issuing the control byte - i2c_regs->ctrl |= I2C_CTRL_IE; - i2c_regs->data = (addr << 1) | 0x00; //7 bit addr and read bit - i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START; //generate start & start writing addr - //update the state so the irq handler knows what's going on - i2c_state = I2C_STATE_CONTROL_BYTE_SENT; - - return true; -} - -//TODO: determine if it's better to read sequentially into the user's buffer, copy on transfer complete, or copy on request (shown below). probably best to copy on request. -bool i2c_async_data_ready(void *buf) { - if(i2c_state == I2C_STATE_DATA_READY) { - i2c_state = I2C_STATE_IDLE; - memcpy(buf, (void *)i2c_buf, (i2c_bufptr - i2c_buf)); //TODO: not really comfortable with this - //printf("Copying %d bytes to user buffer\n", i2c_bufptr-i2c_buf); - return true; - } - return false; -} - - diff --git a/firmware/microblaze/lib/i2c.h b/firmware/microblaze/lib/i2c.h index 77129e922..6ff0e6982 100644 --- a/firmware/microblaze/lib/i2c.h +++ b/firmware/microblaze/lib/i2c.h @@ -22,36 +22,15 @@ #include #include "stdint.h" -typedef enum { I2C_STATE_IDLE, - I2C_STATE_CONTROL_BYTE_SENT, - I2C_STATE_DATA, - I2C_STATE_LAST_BYTE, - I2C_STATE_DATA_READY, - I2C_STATE_ERROR - } i2c_state_t; - -typedef enum { I2C_DIR_WRITE=0, I2C_DIR_READ=1 } i2c_dir_t; - void i2c_init(void); bool i2c_read (unsigned char i2c_addr, unsigned char *buf, unsigned int len); bool i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len); -bool i2c_async_read(uint8_t addr, unsigned int len); -bool i2c_async_write(uint8_t addr, const uint8_t *buf, unsigned int len); -bool i2c_async_data_ready(void *); -//static void i2c_irq_handler(unsigned irq); -void i2c_register_callback(void (*callback)(void)); - -// Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard. -// Which EEPROM is determined by i2c_addr. See i2c_addr.h - bool eeprom_write (int i2c_addr, int eeprom_offset, const void *buf, int len); -bool eeprom_write_async (int i2c_addr, int eeprom_offset, const void *buf, int len, void (*callback)(void)); // Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard. // Which EEPROM is determined by i2c_addr. See i2c_addr.h bool eeprom_read (int i2c_addr, int eeprom_offset, void *buf, int len); -bool eeprom_read_async(int i2c_addr, int eeprom_offset, void *buf, int len, void (*callback)(void)); #endif /* INCLUDED_I2C_H */ diff --git a/firmware/microblaze/lib/i2c_async.c b/firmware/microblaze/lib/i2c_async.c new file mode 100644 index 000000000..05c4c3a09 --- /dev/null +++ b/firmware/microblaze/lib/i2c_async.c @@ -0,0 +1,206 @@ +// +// Copyright 2010 Ettus Research LLC +// +/* + * Copyright 2007,2008 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, see . + */ + + //i2c_async.c: asynchronous (interrupt-driven) routines for I2C. + //separated out here so we can have a small I2C lib for bootloader and + //retain interrupt-driven I2C for the main app. + +#include "memory_map.h" +#include "stdint.h" +#include +#include "pic.h" +#include "nonstdio.h" +#include "i2c_async.h" + + //asynchronous (interrupt-driven) i2c state variables +volatile uint8_t i2c_buf[17]; //tx/rx data transfer buffer +volatile uint8_t *volatile i2c_bufptr = i2c_buf; //ptr to current position +volatile uint8_t i2c_len = 0; //length remaining in current transfer +volatile i2c_state_t i2c_state = I2C_STATE_IDLE; //current I2C transfer state +i2c_dir_t i2c_dir; //I2C transfer direction + +void (*volatile i2c_callback)(void); //function pointer to i2c callback to be called when transaction is complete +static void i2c_irq_handler(unsigned irq); +inline void i2c_async_err(void); + +void i2c_register_handler(void) { + pic_register_handler(IRQ_I2C, i2c_irq_handler); +} + + +static void i2c_irq_handler(unsigned irq) { +//i2c state machine. + + //printf("I2C irq handler\n"); + //first let's make sure nothing is f'ed up + //TODO: uncomment this error checking when we have some way to handle errors +// if(((i2c_regs->cmd_status & I2C_ST_RXACK) != 0) && i2c_dir == I2C_DIR_WRITE) { //we got a NACK and we didn't send it +// printf("\tNACK received\n"); +// i2c_async_err(); +// return; +// }// else printf("\tACK received, proceeding\n"); + + if(i2c_regs->cmd_status & I2C_ST_AL) { + printf("\tArbitration lost!\n"); + i2c_async_err(); + return; + } + + if(i2c_regs->cmd_status & I2C_ST_TIP) { + //printf("\tI2C still busy in interrupt\n"); + return; + } + + //now decide what to do + switch(i2c_state) { + + case I2C_STATE_IDLE: + //this is an error. in idle state, we shouldn't be transferring data, and the fact that the IRQ fired is terrible bad. + printf("AAAAAHHHHH INTERRUPT IN THE IDLE STATE AAAHHHHHHHHH\n"); + i2c_async_err(); + break; + + case I2C_STATE_CONTROL_BYTE_SENT: //here we've sent the control byte, and we're either clocking data in or out now, but we haven't received a byte yet. + case I2C_STATE_DATA: //here we're sending/receiving data and if we're receiving there's data in the data reg + + //if(i2c_state == I2C_STATE_DATA) printf("\tI2C in state DATA with dir=%d and len=%d\n", i2c_dir, i2c_len); + //else printf("\tI2C in state CONTROL_BYTE_SENT with dir=%d and len=%d\n", i2c_dir, i2c_len); + + if(i2c_dir == I2C_DIR_READ) { + if(i2c_state == I2C_STATE_DATA) *(i2c_bufptr++) = i2c_regs->data; + //printf("\tRead %x\n", *(i2c_bufptr-1)); + //set up another data byte + if(i2c_len > 1) //only one more byte to transfer + i2c_regs->cmd_status = I2C_CMD_RD; + else + i2c_regs->cmd_status = I2C_CMD_RD | I2C_CMD_NACK | I2C_CMD_STOP; + } + else if(i2c_dir == I2C_DIR_WRITE) { + //write a byte + //printf("\tWriting %x\n", *i2c_bufptr); + i2c_regs->data = *(i2c_bufptr++); + if(i2c_len > 1) + i2c_regs->cmd_status = I2C_CMD_WR; + else { + //printf("\tGenerating STOP\n"); + i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_STOP; + } + }; + i2c_len--; + if(i2c_len == 0) i2c_state = I2C_STATE_LAST_BYTE; + else i2c_state = I2C_STATE_DATA; //takes care of the addr_sent->data transition + break; + + + case I2C_STATE_LAST_BYTE: //here we've already sent the last read request and the last data is waiting for us. + //printf("\tI2C in state LAST BYTE\n"); + + if(i2c_dir == I2C_DIR_READ) { + *(i2c_bufptr++) = i2c_regs->data; + //printf("\tRead %x\n", *(i2c_bufptr-1)); + i2c_state = I2C_STATE_DATA_READY; + } else { + i2c_state = I2C_STATE_IDLE; + } + i2c_regs->ctrl &= ~I2C_CTRL_IE; //disable interrupts until next time + + if(i2c_callback) { + i2c_callback(); //if we registered a callback, call it! + } + + break; + + + default: //terrible things have happened. + break; + } + +} + +void i2c_register_callback(void (*volatile callback)(void)) { + i2c_callback = callback; +} + +inline void i2c_async_err(void) { + i2c_state = I2C_STATE_IDLE; + i2c_regs->ctrl &= ~I2C_CTRL_IE; + printf("I2C error\n"); +//TODO: set an error flag instead of just dropping things on the floor + i2c_regs->cmd_status = I2C_CMD_STOP; +} + +bool i2c_async_read(uint8_t addr, unsigned int len) { + //printf("Starting async read\n"); + if(i2c_state != I2C_STATE_IDLE) return false; //sorry mario but your i2c is in another castle + if(len == 0) return true; //just idiot-proofing + if(len > sizeof(i2c_buf)) return false; + + //disable I2C interrupts and clear pending interrupts on the I2C device + i2c_regs->ctrl &= ~I2C_CTRL_IE; + i2c_regs->cmd_status |= I2C_CMD_IACK; + + i2c_len = len; + i2c_dir = I2C_DIR_READ; + i2c_bufptr = i2c_buf; + //then set up the transfer by issuing the control byte + i2c_regs->ctrl |= I2C_CTRL_IE; + i2c_regs->data = (addr << 1) | 0x01; //7 bit addr and read bit + i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START; //generate start & start writing addr + //update the state so the irq handler knows what's going on + i2c_state = I2C_STATE_CONTROL_BYTE_SENT; + return true; +} + +bool i2c_async_write(uint8_t addr, const uint8_t *buf, unsigned int len) { + //printf("Starting async write\n"); + if(i2c_state != I2C_STATE_IDLE) return false; //sorry mario but your i2c is in another castle + if(len > sizeof(i2c_buf)) return false; + + //disable I2C interrupts and clear pending interrupts on the I2C device + i2c_regs->ctrl &= ~I2C_CTRL_IE; + i2c_regs->cmd_status |= I2C_CMD_IACK; + + //copy the buffer into our own if writing + memcpy((void *)i2c_buf, buf, len); + + i2c_len = len; + i2c_dir = I2C_DIR_WRITE; + i2c_bufptr = i2c_buf; + //then set up the transfer by issuing the control byte + i2c_regs->ctrl |= I2C_CTRL_IE; + i2c_regs->data = (addr << 1) | 0x00; //7 bit addr and read bit + i2c_regs->cmd_status = I2C_CMD_WR | I2C_CMD_START; //generate start & start writing addr + //update the state so the irq handler knows what's going on + i2c_state = I2C_STATE_CONTROL_BYTE_SENT; + + return true; +} + +//TODO: determine if it's better to read sequentially into the user's buffer, copy on transfer complete, or copy on request (shown below). probably best to copy on request. +bool i2c_async_data_ready(void *buf) { + if(i2c_state == I2C_STATE_DATA_READY) { + i2c_state = I2C_STATE_IDLE; + memcpy(buf, (void *)i2c_buf, (i2c_bufptr - i2c_buf)); //TODO: not really comfortable with this + //printf("Copying %d bytes to user buffer\n", i2c_bufptr-i2c_buf); + return true; + } + return false; +} + diff --git a/firmware/microblaze/lib/i2c_async.h b/firmware/microblaze/lib/i2c_async.h new file mode 100644 index 000000000..e6095fca6 --- /dev/null +++ b/firmware/microblaze/lib/i2c_async.h @@ -0,0 +1,50 @@ +// +// Copyright 2010 Ettus Research LLC +// +/* + * Copyright 2007,2008 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, see . + */ + +#ifndef INCLUDED_I2C_ASYNC_H +#define INCLUDED_I2C_ASYNC_H + +#include +#include "stdint.h" + +typedef enum { I2C_STATE_IDLE, + I2C_STATE_CONTROL_BYTE_SENT, + I2C_STATE_DATA, + I2C_STATE_LAST_BYTE, + I2C_STATE_DATA_READY, + I2C_STATE_ERROR + } i2c_state_t; + +typedef enum { I2C_DIR_WRITE=0, I2C_DIR_READ=1 } i2c_dir_t; + +bool i2c_async_read(uint8_t addr, unsigned int len); +bool i2c_async_write(uint8_t addr, const uint8_t *buf, unsigned int len); +bool i2c_async_data_ready(void *); +//static void i2c_irq_handler(unsigned irq); +void i2c_register_callback(void (*callback)(void)); +void i2c_register_handler(void); + +// Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard. +// Which EEPROM is determined by i2c_addr. See i2c_addr.h + +bool eeprom_write_async (int i2c_addr, int eeprom_offset, const void *buf, int len, void (*callback)(void)); +bool eeprom_read_async(int i2c_addr, int eeprom_offset, void *buf, int len, void (*callback)(void)); + +#endif /* INCLUDED_I2C_ASYNC_H */ diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index 8d666b76b..099aafe83 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -23,6 +23,7 @@ #include "buffer_pool.h" #include "hal_uart.h" #include "i2c.h" +#include "i2c_async.h" #include "mdelay.h" #include "clocks.h" #include "usrp2/fw_common.h" @@ -59,6 +60,7 @@ u2_init(void) // init i2c so we can read our rev pic_init(); // progammable interrupt controller i2c_init(); + i2c_register_handler(); //for using async I2C hal_enable_ints(); get_hw_rev(); diff --git a/firmware/microblaze/usrp2p/bootloader/Makefile.am b/firmware/microblaze/usrp2p/bootloader/Makefile.am index eb72d937d..1fc5daf9c 100644 --- a/firmware/microblaze/usrp2p/bootloader/Makefile.am +++ b/firmware/microblaze/usrp2p/bootloader/Makefile.am @@ -30,7 +30,7 @@ LDADD = $(top_srcdir)/usrp2p/libusrp2p.a noinst_PROGRAMS = \ init_bootloader.elf -init_bootloader_elf_SOURCES = init_bootloader.c i2c_sync.c +init_bootloader_elf_SOURCES = init_bootloader.c .bin.rmi: $(top_srcdir)/bin/bin_to_ram_macro_init.py $< $@ diff --git a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c index 3571313ff..e6c808f37 100644 --- a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c +++ b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c @@ -15,7 +15,8 @@ #include #include #include -#include "i2c_sync.h" +#include +#include "usrp2/fw_common.h" #define SAFE_FLAG_LOCATION 247 @@ -31,14 +32,13 @@ void pic_interrupt_handler() bool find_safe_booted_flag(void) { unsigned char flag_byte; - i2c_read(SAFE_FLAG_LOCATION, &flag_byte, 1); - + eeprom_read(USRP2_I2C_ADDR_MBOARD, SAFE_FLAG_LOCATION, &flag_byte, 1); return (flag_byte == 0x5E); } void set_safe_booted_flag(bool flag) { unsigned char flag_byte = flag ? 0x5E : 0xDC; - i2c_write(SAFE_FLAG_LOCATION, &flag_byte, 1); + eeprom_write(USRP2_I2C_ADDR_MBOARD, SAFE_FLAG_LOCATION, &flag_byte, 1); } @@ -102,7 +102,7 @@ int main(int argc, char *argv[]) { if(is_valid_fpga_image(PROD_FPGA_IMAGE_LOCATION_ADDR)) { puts("Valid production FPGA image found. Attempting to boot."); set_safe_booted_flag(1); - delay(10000); + delay(30000); //so serial output can finish icap_reload_fpga(PROD_FPGA_IMAGE_LOCATION_ADDR); } puts("No valid production FPGA image found.\nAttempting to load production firmware..."); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 12ff1a76f..59e223e75 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -59,6 +59,8 @@ extern "C" { #define USRP2_EE_MBOARD_REV_MSB 0x01 //1 byte #define USRP2_EE_MBOARD_MAC_ADDR 0x02 //6 bytes #define USRP2_EE_MBOARD_IP_ADDR 0x0C //uint32, big-endian +#define USRP2_EE_MBOARD_SERIAL_NUM 0xF8 +#define USRP2_EE_MBOARD_BOOTLOADER_FLAGS 0xF7 typedef enum{ USRP2_CTRL_ID_HUH_WHAT = ' ', -- cgit v1.2.3 From 4a6990c5d3019ca6881464f135a315e3ec022b93 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Fri, 8 Oct 2010 13:38:55 -0700 Subject: USRP2P: Little bit of commonality in the include files. No functional change. --- firmware/microblaze/usrp2p/bootloader/init_bootloader.c | 6 ++---- host/lib/usrp/usrp2/fw_common.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'firmware') diff --git a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c index e6c808f37..2bbbd405e 100644 --- a/firmware/microblaze/usrp2p/bootloader/init_bootloader.c +++ b/firmware/microblaze/usrp2p/bootloader/init_bootloader.c @@ -18,8 +18,6 @@ #include #include "usrp2/fw_common.h" -#define SAFE_FLAG_LOCATION 247 - bool find_safe_booted_flag(void); void set_safe_booted_flag(bool flag); @@ -32,13 +30,13 @@ void pic_interrupt_handler() bool find_safe_booted_flag(void) { unsigned char flag_byte; - eeprom_read(USRP2_I2C_ADDR_MBOARD, SAFE_FLAG_LOCATION, &flag_byte, 1); + eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_BOOTLOADER_FLAGS, &flag_byte, 1); return (flag_byte == 0x5E); } void set_safe_booted_flag(bool flag) { unsigned char flag_byte = flag ? 0x5E : 0xDC; - eeprom_write(USRP2_I2C_ADDR_MBOARD, SAFE_FLAG_LOCATION, &flag_byte, 1); + eeprom_write(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_BOOTLOADER_FLAGS, &flag_byte, 1); } diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 59e223e75..67955c831 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -59,7 +59,6 @@ extern "C" { #define USRP2_EE_MBOARD_REV_MSB 0x01 //1 byte #define USRP2_EE_MBOARD_MAC_ADDR 0x02 //6 bytes #define USRP2_EE_MBOARD_IP_ADDR 0x0C //uint32, big-endian -#define USRP2_EE_MBOARD_SERIAL_NUM 0xF8 #define USRP2_EE_MBOARD_BOOTLOADER_FLAGS 0xF7 typedef enum{ -- cgit v1.2.3 From 5982ec4ee2c6f9efca1c5068e42dc38b822df7dc Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 12 Oct 2010 14:46:41 -0700 Subject: USRP2P: This is surprisingly involved. Adding a consistent interface to deal with hardware revisions. --- firmware/microblaze/usrp2/Makefile.am | 3 +- firmware/microblaze/usrp2p/Makefile.am | 3 +- host/include/uhd/usrp/mboard_rev.hpp | 90 ++++++++++++++++++++++++++++++++++ host/lib/usrp/mboard_rev.cpp | 68 +++++++++++++++++++++++++ host/lib/usrp/usrp2/clock_ctrl.cpp | 36 +++++++------- host/lib/usrp/usrp2/codec_impl.cpp | 4 +- host/lib/usrp/usrp2/fw_common.h | 3 +- host/lib/usrp/usrp2/mboard_impl.cpp | 30 ++++++++---- host/lib/usrp/usrp2/usrp2_clk_regs.hpp | 15 ++++-- host/lib/usrp/usrp2/usrp2_iface.cpp | 4 +- host/lib/usrp/usrp2/usrp2_iface.hpp | 6 +-- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 - host/lib/usrp/usrp2/usrp2_regs.hpp | 2 - 13 files changed, 219 insertions(+), 46 deletions(-) create mode 100644 host/include/uhd/usrp/mboard_rev.hpp create mode 100644 host/lib/usrp/mboard_rev.cpp (limited to 'firmware') diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am index 17f7a4744..e3f57728a 100644 --- a/firmware/microblaze/usrp2/Makefile.am +++ b/firmware/microblaze/usrp2/Makefile.am @@ -22,9 +22,10 @@ AM_CFLAGS = \ AM_LDFLAGS = \ $(COMMON_LFLAGS) \ - libusrp2.a \ -Wl,-defsym -Wl,_TEXT_START_ADDR=0x0050 \ -Wl,-defsym -Wl,_STACK_SIZE=3072 + +LDADD = libusrp2.a ######################################################################## # USRP2 specific library and programs diff --git a/firmware/microblaze/usrp2p/Makefile.am b/firmware/microblaze/usrp2p/Makefile.am index 0d0b60437..a5df3ff08 100644 --- a/firmware/microblaze/usrp2p/Makefile.am +++ b/firmware/microblaze/usrp2p/Makefile.am @@ -22,10 +22,11 @@ AM_CFLAGS = \ AM_LDFLAGS = \ $(COMMON_LFLAGS) \ - libusrp2p.a \ -Wl,-defsym -Wl,_TEXT_START_ADDR=0x8050 \ -Wl,-defsym -Wl,_STACK_SIZE=3072 +LDADD = libusrp2p.a + #all of this here is to relocate the hardware vectors to somewhere normal. RELOCATE_ARGS = \ --change-section-address .vectors.sw_exception+0x8000 \ diff --git a/host/include/uhd/usrp/mboard_rev.hpp b/host/include/uhd/usrp/mboard_rev.hpp new file mode 100644 index 000000000..5307d80c1 --- /dev/null +++ b/host/include/uhd/usrp/mboard_rev.hpp @@ -0,0 +1,90 @@ +// +// 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 . +// + +#ifndef INCLUDED_UHD_USRP_MBOARD_REV_HPP +#define INCLUDED_UHD_USRP_MBOARD_REV_HPP + +#include +#include +#include +#include + +namespace uhd{ namespace usrp{ + + class UHD_API mboard_rev_t : boost::equality_comparable{ + public: + /*! + * Create a mboard rev from an integer. + * \param rev the integer representation + */ + mboard_rev_t(boost::uint16_t rev = 0xffff); + + /*! + * Obtain a mboard rev that represents an invalid/uninit mboard ID + * \return the mboard rev with the 0xffff rev. + */ + static mboard_rev_t none(void); + + /*! + * Create a new mboard rev from an integer representation. + * \param uint16 an unsigned 16 bit integer + * \return a new mboard rev containing the integer + */ + static mboard_rev_t from_uint16(boost::uint16_t uint16); + + /*! + * Get the mboard rev represented as an integer. + * \return an unsigned 16 bit integer representation + */ + boost::uint16_t to_uint16(void) const; + + /*! + * Create a new mboard rev from a string representation. + * If the string has a 0x prefix, it will be parsed as hex. + * \param string a numeric string, possibly hex + * \return a new dboard id containing the integer + */ + static mboard_rev_t from_string(const std::string &string); + + /*! + * Get the mboard rev represented as an integer. + * \return a hex string representation with 0x prefix + */ + std::string to_string(void) const; + + /*! + * Get the pretty print representation of this mboard rev. + * \return a string with the mboard name and rev number + */ + std::string to_pp_string(void) const; + + private: + boost::uint16_t _rev; //internal representation + }; + + /*! + * Comparator operator overloaded for mboard rev. + * The boost::equality_comparable provides the !=. + * \param lhs the dboard id to the left of the operator + * \param rhs the dboard id to the right of the operator + * \return true when the mboard revs are equal + */ + UHD_API bool operator==(const mboard_rev_t &lhs, const mboard_rev_t &rhs); + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MBOARD_REV_HPP */ diff --git a/host/lib/usrp/mboard_rev.cpp b/host/lib/usrp/mboard_rev.cpp new file mode 100644 index 000000000..8206d12af --- /dev/null +++ b/host/lib/usrp/mboard_rev.cpp @@ -0,0 +1,68 @@ +// +// 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 + +using namespace uhd::usrp; + +mboard_rev_t::mboard_rev_t(boost::uint16_t id){ + _rev = rev; +} + +mboard_rev_t mboard_rev_t::none(void){ + return mboard_rev_t(); +} + +mboard_rev_t mboard_rev_t::from_uint16(boost::uint16_t uint16){ + return mboard_rev_t(uint16); +} + +boost::uint16_t mboard_rev_t::to_uint16(void) const{ + return _rev; +} + +//used with lexical cast to parse a hex string +template struct to_hex{ + T value; + operator T() const {return value;} + friend std::istream& operator>>(std::istream& in, to_hex& out){ + in >> std::hex >> out.value; + return in; + } +}; + +mboard_rev_t mboard_rev_t::from_string(const std::string &string){ + if (string.substr(0, 2) == "0x"){ + return mboard_rev_t::from_uint16(boost::lexical_cast >(string)); + } + return mboard_rev_t::from_uint16(boost::lexical_cast(string)); +} + +std::string mboard_rev_t::to_string(void) const{ + return str(boost::format("0x%04x") % this->to_uint16()); +} + +//Note: to_pp_string is implemented in the dboard manager +//because it needs access to the dboard registration table + +bool uhd::usrp::operator==(const mboard_rev_t &lhs, const mboard_rev_t &rhs){ + return lhs.to_uint16() == rhs.to_uint16(); +} diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index c3dc4917e..8887faf12 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -17,6 +17,7 @@ #include "clock_ctrl.hpp" #include "ad9510_regs.hpp" +#include #include "usrp2_regs.hpp" //spi slave constants #include "usrp2_clk_regs.hpp" #include @@ -31,9 +32,7 @@ using namespace uhd; class usrp2_clock_ctrl_impl : public usrp2_clock_ctrl{ public: usrp2_clock_ctrl_impl(usrp2_iface::sptr iface){ - _iface = iface; //_iface has get_hw_rev(), which lets us know if it's a USRP2+ (>=0x80) or USRP2 (<0x80). - - clk_regs = usrp2_clk_regs_t(_iface->get_hw_rev()); + clk_regs = usrp2_clk_regs_t(iface->get_hw_rev()); _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; this->write_reg(clk_regs.pll_3); @@ -86,16 +85,13 @@ public: } void enable_mimo_clock_out(bool enb){ - //FIXME TODO put this revision read in a common place - boost::uint8_t rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0); - //calculate the low and high dividers size_t divider = size_t(this->get_master_clock_rate()/10e6); size_t high = divider/2; size_t low = divider - high; - switch(rev_hi){ - case 3: //clock 2 + switch(clk_regs.exp){ + case 2: //U2 rev 3 _ad9510_regs.power_down_lvpecl_out2 = enb? ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_NORMAL : ad9510_regs_t::POWER_DOWN_LVPECL_OUT2_SAFE_PD; @@ -104,11 +100,9 @@ public: _ad9510_regs.divider_low_cycles_out2 = low - 1; _ad9510_regs.divider_high_cycles_out2 = high - 1; _ad9510_regs.bypass_divider_out2 = 0; - this->write_reg(0x3e); - this->write_reg(0x4c); break; - case 4: //clock 5 + case 5: //U2 rev 4 _ad9510_regs.power_down_lvds_cmos_out5 = enb? 0 : 1; _ad9510_regs.lvds_cmos_select_out5 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT5_LVDS; _ad9510_regs.output_level_lvds_out5 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT5_1_75MA; @@ -116,19 +110,26 @@ public: _ad9510_regs.divider_low_cycles_out5 = low - 1; _ad9510_regs.divider_high_cycles_out5 = high - 1; _ad9510_regs.bypass_divider_out5 = 0; - this->write_reg(0x41); - this->write_reg(0x52); + break; + + case 6: //U2+ + _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1; + _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_LVDS; + _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA; + //set the registers (divider - 1) + _ad9510_regs.divider_low_cycles_out6 = low - 1; + _ad9510_regs.divider_high_cycles_out6 = high - 1; + _ad9510_regs.bypass_divider_out5 = 0; break; - //TODO FIXME do i want to throw, what about uninitialized boards? - //default: throw std::runtime_error("unknown rev hi in mboard eeprom"); - default: std::cerr << "unknown rev hi: " << rev_hi << std::endl; + default: } + this->write_reg(clk_regs.output(clk_regs.exp)); + this->write_reg(clk_regs.div_lo(clk_regs.exp)); this->update_regs(); } //uses output clock 7 (cmos) - //this clock is the same between USRP2 and USRP2+ and so this fn does not get a switch statement void enable_rx_dboard_clock(bool enb){ _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1; _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS; @@ -297,7 +298,6 @@ private: } usrp2_clk_regs_t clk_regs; - usrp2_iface::sptr _iface; ad9510_regs_t _ad9510_regs; }; diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp index db98e50ab..04a11d922 100644 --- a/host/lib/usrp/usrp2/codec_impl.cpp +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -67,7 +67,7 @@ void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ return; case CODEC_PROP_GAIN_NAMES: - if(_iface->get_hw_rev() >= USRP2P_FIRST_HW_REV) { + if(_iface->get_hw_rev().to_uint16() >= USRP2P_FIRST_HW_REV) { val = prop_names_t(codec_rx_gain_ranges.keys()); } else val = prop_names_t(); return; @@ -94,7 +94,7 @@ void usrp2_mboard_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ switch(key.as()) { case CODEC_PROP_GAIN_I: case CODEC_PROP_GAIN_Q: - if(_iface->get_hw_rev() < USRP2P_FIRST_HW_REV) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P + if(_iface->get_hw_rev().to_uint16() < USRP2P_FIRST_HW_REV) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P gain = val.as(); this->rx_codec_set_gain(gain, key.name); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 67955c831..6c9596092 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -55,8 +55,7 @@ extern "C" { //////////////////////////////////////////////////////////////////////// // EEPROM Layout //////////////////////////////////////////////////////////////////////// -#define USRP2_EE_MBOARD_REV_LSB 0x00 //1 byte -#define USRP2_EE_MBOARD_REV_MSB 0x01 //1 byte +#define USRP2_EE_MBOARD_REV 0x00 //2 bytes, little-endian (historic, don't blame me) #define USRP2_EE_MBOARD_MAC_ADDR 0x02 //6 bytes #define USRP2_EE_MBOARD_IP_ADDR 0x0C //uint32, big-endian #define USRP2_EE_MBOARD_BOOTLOADER_FLAGS 0xF7 diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index e0e0d726e..6ee6d03a1 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -49,12 +50,9 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface = usrp2_iface::make(ctrl_transport); //extract the mboard rev numbers - _rev_lo = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_LSB, 1).at(0); - _rev_hi = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, 1).at(0); - - //set the device revision (USRP2 or USRP2+) based on the above - _iface->set_hw_rev((_rev_hi << 8) | _rev_lo); - + byte_vector_t rev_bytes = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, 2); + _iface->set_hw_rev(mboard_rev_t::from_uint16(rev_bytes.at(0) | (revbytes.at(1) << 8))); + //contruct the interfaces to mboard perifs _clock_ctrl = usrp2_clock_ctrl::make(_iface); _codec_ctrl = usrp2_codec_ctrl::make(_iface); @@ -224,12 +222,17 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){ val = boost::asio::ip::address_v4(bytes).to_string(); return; } - } + + if (key.as() == "hw-rev"){ + //extract the mboard rev numbers + val = _iface->get_hw_rev().to_string(); + return; + } //handle the get request conditioned on the key switch(key.as()){ case MBOARD_PROP_NAME: - val = str(boost::format("usrp2 mboard%d - rev %d:%d") % _index % _rev_hi % _rev_lo); + val = str(boost::format("usrp2 mboard%d - rev %s") % _index % _iface->get_hw_rev().to_string()); return; case MBOARD_PROP_OTHERS:{ @@ -321,9 +324,18 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){ _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_IP_ADDR, bytes); return; } + + if (key.as() == "hw-rev"){ + mboard_rev_t rev = mboard_rev_t::from_string(val.as()); + byte_vector_t revbytes(2); + revbytes(1) = rev.to_uint16() >> 8; + revbytes(0) = rev.to_uint16() & 0xff; + _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, revbytes); + _iface->set_hw_rev(rev); //so the iface knows what rev it is + return; } - //handle the get request conditioned on the key + //handle the set request conditioned on the key switch(key.as()){ case MBOARD_PROP_CLOCK_CONFIG: diff --git a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp index d057fb342..edbdfa15d 100644 --- a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp @@ -18,19 +18,24 @@ #ifndef INCLUDED_USRP2_CLK_REGS_HPP #define INCLUDED_USRP2_CLK_REGS_HPP +#include #include "usrp2_regs.hpp" class usrp2_clk_regs_t { public: usrp2_clk_regs_t(void) { ; } - usrp2_clk_regs_t(int hw_rev) { + usrp2_clk_regs_t(uhd::usrp::mboard_rev_t hw_rev) { test = 0; fpga = 1; - adc = (hw_rev>=USRP2P_FIRST_HW_REV) ? 2 : 4; + adc = (hw_rev.is_usrp2p()) ? 2 : 4; dac = 3; - serdes = (hw_rev>=USRP2P_FIRST_HW_REV) ? 4 : 2; //only used by usrp2+ - tx_db = (hw_rev>=USRP2P_FIRST_HW_REV) ? 5 : 6; - exp = (hw_rev>=USRP2P_FIRST_HW_REV) ? 6 : 5; + serdes = (hw_rev.is_usrp2p()) ? 4 : 2; //only used by usrp2+ + tx_db = (hw_rev.is_usrp2p()) ? 5 : 6; + + if(hw_rev.major() == 3) exp = 2; + else if(hw_rev.major() >= 4) exp = 5; + else if(hw_rev.major() > 10) exp = 6; + rx_db = 7; } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 0771c4945..7ce5cc936 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -260,12 +260,12 @@ public: /*********************************************************************** * Get/set hardware revision **********************************************************************/ - void set_hw_rev(int rev) { + void set_hw_rev(mboard_rev_t rev) { hw_rev = rev; regs = usrp2_get_regs(rev); //might be a better place to do this } - int get_hw_rev(void) { + mboard_rev_t get_hw_rev(void) { return hw_rev; } diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 55fbfa7e4..fe2687d02 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -112,12 +112,12 @@ public: * Set the hardware revision number. Also selects the proper register set for the device. * \param rev the 16-bit revision */ - virtual void set_hw_rev(int rev) = 0; + virtual void set_hw_rev(uhd::usrp::mboard_rev_t rev) = 0; /*! Return the hardware revision number * \return hardware revision */ - virtual int get_hw_rev(void) = 0; + virtual uhd::usrp::mboard_rev_t get_hw_rev(void) = 0; /*! * Register map selected from USRP2/USRP2+. @@ -126,7 +126,7 @@ public: /*! * Hardware revision as returned by the device. */ - int hw_rev; + uhd::usrp::mboard_rev_t hw_rev; }; #endif /* INCLUDED_USRP2_IFACE_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index b81711e2b..1ebd90ca4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -95,7 +95,6 @@ public: private: size_t _index; - int _rev_hi, _rev_lo; const size_t _recv_frame_size; //properties for this mboard diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index f74c78b7b..8dae843ab 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -18,8 +18,6 @@ #ifndef INCLUDED_USRP2_REGS_HPP #define INCLUDED_USRP2_REGS_HPP -//these are used to set the - #define USRP2_MISC_OUTPUT_BASE 0xD400 #define USRP2_GPIO_BASE 0xC800 #define USRP2_ATR_BASE 0xE400 -- cgit v1.2.3 From 5b4cbfe4616492d96ad1b48578cf2d94e1216bf4 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 12 Oct 2010 16:26:19 -0700 Subject: USRP2P: mboard rev works through props interface. Added usrp2_burn_mb_rev.cpp to utils. It is not installed to the utils install dir. Not all happy with the mboard_rev setup -- is_usrp2p() is too specific for a generalized mboard_rev concept. I'm not sure where else to put it so for now it stays. --- firmware/microblaze/lib/u2_init.c | 4 +- host/include/uhd/usrp/mboard_rev.hpp | 34 +++++++++++++-- host/lib/usrp/CMakeLists.txt | 1 + host/lib/usrp/mboard_rev.cpp | 29 +++++++++++-- host/lib/usrp/usrp2/clock_ctrl.cpp | 6 ++- host/lib/usrp/usrp2/codec_ctrl.cpp | 10 ++--- host/lib/usrp/usrp2/codec_impl.cpp | 4 +- host/lib/usrp/usrp2/mboard_impl.cpp | 18 ++++---- host/lib/usrp/usrp2/usrp2_iface.cpp | 4 +- host/lib/usrp/usrp2/usrp2_iface.hpp | 1 + host/lib/usrp/usrp2/usrp2_regs.cpp | 11 ++--- host/lib/usrp/usrp2/usrp2_regs.hpp | 6 ++- host/utils/CMakeLists.txt | 3 ++ host/utils/usrp2_burn_mb_rev.cpp | 82 ++++++++++++++++++++++++++++++++++++ 14 files changed, 180 insertions(+), 33 deletions(-) create mode 100644 host/utils/usrp2_burn_mb_rev.cpp (limited to 'firmware') diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index 099aafe83..3c8f5f02a 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -35,8 +35,8 @@ unsigned char u2_hw_rev_minor; static inline void get_hw_rev(void) { - bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_LSB, &u2_hw_rev_minor, 1); - ok &= eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV_MSB, &u2_hw_rev_major, 1); + bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, &u2_hw_rev_minor, 1); + ok &= eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV+1, &u2_hw_rev_major, 1); } /* diff --git a/host/include/uhd/usrp/mboard_rev.hpp b/host/include/uhd/usrp/mboard_rev.hpp index 5307d80c1..be968d01d 100644 --- a/host/include/uhd/usrp/mboard_rev.hpp +++ b/host/include/uhd/usrp/mboard_rev.hpp @@ -25,7 +25,7 @@ namespace uhd{ namespace usrp{ - class UHD_API mboard_rev_t : boost::equality_comparable{ + class UHD_API mboard_rev_t : boost::equality_comparable, boost::less_than_comparable{ public: /*! * Create a mboard rev from an integer. @@ -71,6 +71,24 @@ namespace uhd{ namespace usrp{ * \return a string with the mboard name and rev number */ std::string to_pp_string(void) const; + + /*! + * Tell you if you're USRP2 or USRP2+ + * \return true if USRP2+, false if USRP2 + */ + bool is_usrp2p(void) const; + + /*! + * Get the major revision number + * \return major revision number + */ + boost::uint8_t major(void) const; + + /*! + * Get the minor revision number + * \return minor revision number + */ + boost::uint8_t minor(void) const; private: boost::uint16_t _rev; //internal representation @@ -79,11 +97,21 @@ namespace uhd{ namespace usrp{ /*! * Comparator operator overloaded for mboard rev. * The boost::equality_comparable provides the !=. - * \param lhs the dboard id to the left of the operator - * \param rhs the dboard id to the right of the operator + * \param lhs the mboard rev to the left of the operator + * \param rhs the mboard rev to the right of the operator * \return true when the mboard revs are equal */ UHD_API bool operator==(const mboard_rev_t &lhs, const mboard_rev_t &rhs); + + /*! + * Comparator operator overloaded for mboard rev. + * The boost::less_than_comparable provides the >, <=, >=. + * \param lhs the mboard rev to the left of the operator + * \param rhs the mboard rev to the right of the operator + * \return true when lhs < rhs + */ + + UHD_API bool operator<(const mboard_rev_t &lhs, const mboard_rev_t &rhs); }} //namespace diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 69a190bfa..fd4eb1016 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -23,6 +23,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_id.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dboard_manager.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/mboard_rev.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/misc_utils.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp diff --git a/host/lib/usrp/mboard_rev.cpp b/host/lib/usrp/mboard_rev.cpp index 8206d12af..41600951f 100644 --- a/host/lib/usrp/mboard_rev.cpp +++ b/host/lib/usrp/mboard_rev.cpp @@ -23,7 +23,9 @@ using namespace uhd::usrp; -mboard_rev_t::mboard_rev_t(boost::uint16_t id){ +static const mboard_rev_t usrp2p_first_hw_rev = mboard_rev_t(0x0A00); + +mboard_rev_t::mboard_rev_t(boost::uint16_t rev){ _rev = rev; } @@ -60,9 +62,30 @@ std::string mboard_rev_t::to_string(void) const{ return str(boost::format("0x%04x") % this->to_uint16()); } -//Note: to_pp_string is implemented in the dboard manager -//because it needs access to the dboard registration table +std::string mboard_rev_t::to_pp_string(void) const{ + if(this->is_usrp2p()) { + return str(boost::format("USRP2+, major rev %i, minor rev %i") % int(this->major()) % int(this->minor())); + } else { + return str(boost::format("USRP2, major rev %i, minor rev %i") % int(this->major()) % int(this->minor())); + } +} + +bool mboard_rev_t::is_usrp2p(void) const{ + return _rev >= usrp2p_first_hw_rev; +} + +boost::uint8_t mboard_rev_t::major(void) const{ + return _rev >> 8; +} + +boost::uint8_t mboard_rev_t::minor(void) const{ + return _rev & 0xff; +} bool uhd::usrp::operator==(const mboard_rev_t &lhs, const mboard_rev_t &rhs){ return lhs.to_uint16() == rhs.to_uint16(); } + +bool uhd::usrp::operator<(const mboard_rev_t &lhs, const mboard_rev_t &rhs){ + return lhs.to_uint16() < rhs.to_uint16(); +} diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 8887faf12..c652b592b 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -32,7 +32,8 @@ using namespace uhd; class usrp2_clock_ctrl_impl : public usrp2_clock_ctrl{ public: usrp2_clock_ctrl_impl(usrp2_iface::sptr iface){ - clk_regs = usrp2_clk_regs_t(iface->get_hw_rev()); + _iface = iface; + clk_regs = usrp2_clk_regs_t(_iface->get_hw_rev()); _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA; this->write_reg(clk_regs.pll_3); @@ -123,6 +124,7 @@ public: break; default: + break; } this->write_reg(clk_regs.output(clk_regs.exp)); this->write_reg(clk_regs.div_lo(clk_regs.exp)); @@ -296,6 +298,8 @@ private: this->write_reg(clk_regs.div_hi(clk_regs.adc)); this->update_regs(); } + + usrp2_iface::sptr _iface; usrp2_clk_regs_t clk_regs; ad9510_regs_t _ad9510_regs; diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index 22a892f02..533534bd0 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -59,7 +59,7 @@ public: } //power-up adc - if(_iface->get_hw_rev() < USRP2P_FIRST_HW_REV) { //if we're on a USRP2 + if(!_iface->get_hw_rev().is_usrp2p()) { //if we're on a USRP2 _iface->poke32(_iface->regs.misc_ctrl_adc, U2_FLAG_MISC_CTRL_ADC_ON); } else { //we're on a USRP2+ _ads62p44_regs.reset = 1; @@ -77,7 +77,7 @@ public: this->send_ad9777_reg(0); //power-down adc - if(_iface->get_hw_rev() < USRP2P_FIRST_HW_REV) { //if we're on a USRP2 + if(!_iface->get_hw_rev().is_usrp2p()) { //if we're on a USRP2 _iface->poke32(_iface->regs.misc_ctrl_adc, U2_FLAG_MISC_CTRL_ADC_OFF); } else { //we're on a USRP2+ //send a global power-down to the ADC here... it will get lifted on reset @@ -87,21 +87,21 @@ public: } void set_rx_digital_gain(float gain) { //fine digital gain - if(_iface->get_hw_rev() >= USRP2P_FIRST_HW_REV) { + if(_iface->get_hw_rev().is_usrp2p()) { _ads62p44_regs.fine_gain = int(gain/0.5); this->send_ads62p44_reg(0x17); } else UHD_THROW_INVALID_CODE_PATH(); //should never have been called for USRP2 } void set_rx_digital_fine_gain(float gain) { //gain correction - if(_iface->get_hw_rev() >= USRP2P_FIRST_HW_REV) { + if(_iface->get_hw_rev().is_usrp2p()) { _ads62p44_regs.gain_correction = int(gain / 0.05); this->send_ads62p44_reg(0x1A); } else UHD_THROW_INVALID_CODE_PATH(); //should never have been called for USRP2 } void set_rx_analog_gain(bool gain) { //turns on/off analog 3.5dB preamp - if(_iface->get_hw_rev() >= USRP2P_FIRST_HW_REV) { + if(_iface->get_hw_rev().is_usrp2p()) { _ads62p44_regs.coarse_gain = gain ? ads62p44_regs_t::COARSE_GAIN_3_5DB : ads62p44_regs_t::COARSE_GAIN_0DB; this->send_ads62p44_reg(0x14); } else UHD_THROW_INVALID_CODE_PATH(); diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp index 04a11d922..6065b6c28 100644 --- a/host/lib/usrp/usrp2/codec_impl.cpp +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -67,7 +67,7 @@ void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ return; case CODEC_PROP_GAIN_NAMES: - if(_iface->get_hw_rev().to_uint16() >= USRP2P_FIRST_HW_REV) { + if(_iface->get_hw_rev().is_usrp2p()) { val = prop_names_t(codec_rx_gain_ranges.keys()); } else val = prop_names_t(); return; @@ -94,7 +94,7 @@ void usrp2_mboard_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ switch(key.as()) { case CODEC_PROP_GAIN_I: case CODEC_PROP_GAIN_Q: - if(_iface->get_hw_rev().to_uint16() < USRP2P_FIRST_HW_REV) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P + if(!_iface->get_hw_rev().is_usrp2p()) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P gain = val.as(); this->rx_codec_set_gain(gain, key.name); diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 6ee6d03a1..3a7048cdd 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -51,7 +51,7 @@ usrp2_mboard_impl::usrp2_mboard_impl( //extract the mboard rev numbers byte_vector_t rev_bytes = _iface->read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, 2); - _iface->set_hw_rev(mboard_rev_t::from_uint16(rev_bytes.at(0) | (revbytes.at(1) << 8))); + _iface->set_hw_rev(mboard_rev_t::from_uint16(rev_bytes.at(0) | (rev_bytes.at(1) << 8))); //contruct the interfaces to mboard perifs _clock_ctrl = usrp2_clock_ctrl::make(_iface); @@ -158,7 +158,7 @@ void usrp2_mboard_impl::update_clock_config(void){ _iface->poke32(_iface->regs.time64_flags, pps_flags); //clock source ref 10mhz - if(_iface->get_hw_rev() >= USRP2P_FIRST_HW_REV) { + if(_iface->get_hw_rev().is_usrp2p()) { switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; @@ -176,7 +176,7 @@ void usrp2_mboard_impl::update_clock_config(void){ //clock source ref 10mhz bool use_external = (_clock_config.ref_source != clock_config_t::REF_INT) - || (_iface->get_hw_rev() >= USRP2P_FIRST_HW_REV); //USRP2P has an internal 10MHz TCXO + || (_iface->get_hw_rev().is_usrp2p()); //USRP2P has an internal 10MHz TCXO _clock_ctrl->enable_external_ref(use_external); } @@ -224,10 +224,11 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){ } if (key.as() == "hw-rev"){ - //extract the mboard rev numbers + //extract the mboard rev number val = _iface->get_hw_rev().to_string(); return; } + } //handle the get request conditioned on the key switch(key.as()){ @@ -327,12 +328,13 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){ if (key.as() == "hw-rev"){ mboard_rev_t rev = mboard_rev_t::from_string(val.as()); - byte_vector_t revbytes(2); - revbytes(1) = rev.to_uint16() >> 8; - revbytes(0) = rev.to_uint16() & 0xff; - _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, revbytes); + byte_vector_t rev_bytes(2); + rev_bytes[1] = rev.to_uint16() >> 8; + rev_bytes[0] = rev.to_uint16() & 0xff; + _iface->write_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, rev_bytes); _iface->set_hw_rev(rev); //so the iface knows what rev it is return; + } } //handle the set request conditioned on the key diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 7ce5cc936..bce859629 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -260,12 +260,12 @@ public: /*********************************************************************** * Get/set hardware revision **********************************************************************/ - void set_hw_rev(mboard_rev_t rev) { + void set_hw_rev(uhd::usrp::mboard_rev_t rev) { hw_rev = rev; regs = usrp2_get_regs(rev); //might be a better place to do this } - mboard_rev_t get_hw_rev(void) { + uhd::usrp::mboard_rev_t get_hw_rev(void) { return hw_rev; } diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index fe2687d02..53a8e4bc8 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "fw_common.h" #include "usrp2_regs.hpp" diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp index 49f077221..f9b54b76e 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.cpp +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -15,19 +15,20 @@ // along with this program. If not, see . // +#include #include "usrp2_regs.hpp" int sr_addr(int misc_output_base, int sr) { return misc_output_base + 4 * sr; } -usrp2_regs_t usrp2_get_regs(int hw_rev) { +usrp2_regs_t usrp2_get_regs(uhd::usrp::mboard_rev_t hw_rev) { //how about you just make this dependent on hw_rev instead of doing the init before main, and give up the const globals, since the application won't ever need both. - const int misc_output_base = (hw_rev>=USRP2P_FIRST_HW_REV) ? USRP2P_MISC_OUTPUT_BASE : USRP2_MISC_OUTPUT_BASE, - gpio_base = (hw_rev>=USRP2P_FIRST_HW_REV) ? USRP2P_GPIO_BASE : USRP2_GPIO_BASE, - atr_base = (hw_rev>=USRP2P_FIRST_HW_REV) ? USRP2P_ATR_BASE : USRP2_ATR_BASE, - bp_base = (hw_rev>=USRP2P_FIRST_HW_REV) ? USRP2P_BP_STATUS_BASE : USRP2_BP_STATUS_BASE; + const int misc_output_base = (hw_rev.is_usrp2p()) ? USRP2P_MISC_OUTPUT_BASE : USRP2_MISC_OUTPUT_BASE, + gpio_base = (hw_rev.is_usrp2p()) ? USRP2P_GPIO_BASE : USRP2_GPIO_BASE, + atr_base = (hw_rev.is_usrp2p()) ? USRP2P_ATR_BASE : USRP2_ATR_BASE, + bp_base = (hw_rev.is_usrp2p()) ? USRP2P_BP_STATUS_BASE : USRP2_BP_STATUS_BASE; usrp2_regs_t x; x.sr_misc = 0; diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 8dae843ab..bb15ed496 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -18,6 +18,8 @@ #ifndef INCLUDED_USRP2_REGS_HPP #define INCLUDED_USRP2_REGS_HPP +#include + #define USRP2_MISC_OUTPUT_BASE 0xD400 #define USRP2_GPIO_BASE 0xC800 #define USRP2_ATR_BASE 0xE400 @@ -28,7 +30,7 @@ #define USRP2P_ATR_BASE 0x3800 #define USRP2P_BP_STATUS_BASE 0x3300 -#define USRP2P_FIRST_HW_REV 0x0A00 +const uhd::usrp::mboard_rev_t USRP2P_FIRST_HW_REV(0x0A00); typedef struct { int sr_misc; @@ -101,7 +103,7 @@ typedef struct { extern const usrp2_regs_t usrp2_regs; //the register definitions, set in usrp2_regs.cpp and usrp2p_regs.cpp -usrp2_regs_t usrp2_get_regs(int hw_rev); +usrp2_regs_t usrp2_get_regs(uhd::usrp::mboard_rev_t hw_rev); //////////////////////////////////////////////////// // Settings Bus, Slave #7, Not Byte Addressable! diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index a95864ca7..083c7629c 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -45,6 +45,9 @@ TARGET_LINK_LIBRARIES(usrp1_init_eeprom uhd) ADD_EXECUTABLE(usrp1_serial_burner usrp1_serial_burner.cpp) TARGET_LINK_LIBRARIES(usrp1_serial_burner uhd) +ADD_EXECUTABLE(usrp2_burn_mb_rev usrp2_burn_mb_rev.cpp) +TARGET_LINK_LIBRARIES(usrp2_burn_mb_rev uhd) + INSTALL(TARGETS usrp2_addr_burner usrp_burn_db_eeprom diff --git a/host/utils/usrp2_burn_mb_rev.cpp b/host/utils/usrp2_burn_mb_rev.cpp new file mode 100644 index 000000000..59b072d17 --- /dev/null +++ b/host/utils/usrp2_burn_mb_rev.cpp @@ -0,0 +1,82 @@ +// +// 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 +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +namespace po = boost::program_options; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + //command line variables + std::string args; + + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("args", po::value(&args)->default_value(""), "device address args [default = \"\"]") + ("rev", po::value(), "mboard rev to burn, omit for readback") + ; + + 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 Burn MB HW revision %s") % desc << std::endl; + std::cout << boost::format( + "Omit the rev argument to perform readback,\n" + "Or specify a new rev to burn into the eeprom.\n" + ) << std::endl; + return ~0; + } + + //make the device and extract the mboard + device::sptr dev = device::make(args); + wax::obj u2_mb = (*dev)[DEVICE_PROP_MBOARD]; + + //read the current mboard rev from eeprom + if (vm.count("rev") == 0){ + std::cout << "Getting rev..." << std::endl; + uhd::usrp::mboard_rev_t rev = mboard_rev_t::from_string(u2_mb[std::string("hw-rev")].as()); + std::cout << boost::format(" Current rev: %s") % rev.to_pp_string() << std::endl; + } + + //write a new mboard rev to eeprom + else{ + mboard_rev_t rev = mboard_rev_t::from_string(vm["rev"].as()); + std::cout << "Setting mboard rev..." << std::endl; + std::cout << boost::format(" New rev: %s") % rev.to_pp_string() << std::endl; + u2_mb[std::string("hw-rev")] = rev.to_string(); + } + + std::cout << " Done" << std::endl << std::endl; + return 0; +} -- cgit v1.2.3 From e0b3b4e3dd9f22d27e9465bba0c978a488733aae Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Wed, 10 Nov 2010 16:23:11 -0800 Subject: U2P: Ripped out the mboard_rev_t structure in favor of an enum in usrp2_regs.hpp and some logic. Also change ethernet.c to move generic code to eth_lib. --- firmware/microblaze/usrp2p/ethernet.c | 4 +- host/lib/usrp/usrp2/CMakeLists.txt | 2 - host/lib/usrp/usrp2/clock_ctrl.cpp | 1 - host/lib/usrp/usrp2/codec_ctrl.cpp | 10 +-- host/lib/usrp/usrp2/codec_impl.cpp | 4 +- host/lib/usrp/usrp2/mboard_impl.cpp | 5 +- host/lib/usrp/usrp2/mboard_rev.cpp | 89 -------------------- host/lib/usrp/usrp2/mboard_rev.hpp | 114 -------------------------- host/lib/usrp/usrp2/usrp2_clk_regs.hpp | 26 ++++-- host/lib/usrp/usrp2/usrp2_iface.cpp | 26 +++--- host/lib/usrp/usrp2/usrp2_iface.hpp | 21 ++--- host/lib/usrp/usrp2/usrp2_regs.cpp | 14 ++-- host/lib/usrp/usrp2/usrp2_regs.hpp | 144 +++++++++++++++++---------------- 13 files changed, 123 insertions(+), 337 deletions(-) delete mode 100644 host/lib/usrp/usrp2/mboard_rev.cpp delete mode 100644 host/lib/usrp/usrp2/mboard_rev.hpp (limited to 'firmware') diff --git a/firmware/microblaze/usrp2p/ethernet.c b/firmware/microblaze/usrp2p/ethernet.c index 660f28934..36d6a17ca 100644 --- a/firmware/microblaze/usrp2p/ethernet.c +++ b/firmware/microblaze/usrp2p/ethernet.c @@ -294,7 +294,7 @@ unprogrammed(const void *t, size_t len) } //////////////////// MAC Addr Stuff /////////////////////// - +/* static int8_t src_mac_addr_initialized = false; static eth_mac_addr_t src_mac_addr = {{ 0x00, 0x50, 0xC2, 0x85, 0x3f, 0xff @@ -373,7 +373,7 @@ bool set_ip_addr(const struct ip_addr *t){ return ok; } - +*/ int ethernet_check_errors(void) { diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index a09c833bd..f7984fce5 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -48,8 +48,6 @@ IF(ENABLE_USRP2) ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_rev.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_rev.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.cpp diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 8eaafe680..1f8e65ce6 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -17,7 +17,6 @@ #include "clock_ctrl.hpp" #include "ad9510_regs.hpp" -#include "mboard_rev.hpp" #include "usrp2_regs.hpp" //spi slave constants #include "usrp2_clk_regs.hpp" #include diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index 533534bd0..8680c285a 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -59,7 +59,7 @@ public: } //power-up adc - if(!_iface->get_hw_rev().is_usrp2p()) { //if we're on a USRP2 + if(!_iface->is_usrp2p()) { //if we're on a USRP2 _iface->poke32(_iface->regs.misc_ctrl_adc, U2_FLAG_MISC_CTRL_ADC_ON); } else { //we're on a USRP2+ _ads62p44_regs.reset = 1; @@ -77,7 +77,7 @@ public: this->send_ad9777_reg(0); //power-down adc - if(!_iface->get_hw_rev().is_usrp2p()) { //if we're on a USRP2 + if(!_iface->is_usrp2p()) { //if we're on a USRP2 _iface->poke32(_iface->regs.misc_ctrl_adc, U2_FLAG_MISC_CTRL_ADC_OFF); } else { //we're on a USRP2+ //send a global power-down to the ADC here... it will get lifted on reset @@ -87,21 +87,21 @@ public: } void set_rx_digital_gain(float gain) { //fine digital gain - if(_iface->get_hw_rev().is_usrp2p()) { + if(_iface->is_usrp2p()) { _ads62p44_regs.fine_gain = int(gain/0.5); this->send_ads62p44_reg(0x17); } else UHD_THROW_INVALID_CODE_PATH(); //should never have been called for USRP2 } void set_rx_digital_fine_gain(float gain) { //gain correction - if(_iface->get_hw_rev().is_usrp2p()) { + if(_iface->is_usrp2p()) { _ads62p44_regs.gain_correction = int(gain / 0.05); this->send_ads62p44_reg(0x1A); } else UHD_THROW_INVALID_CODE_PATH(); //should never have been called for USRP2 } void set_rx_analog_gain(bool gain) { //turns on/off analog 3.5dB preamp - if(_iface->get_hw_rev().is_usrp2p()) { + if(_iface->is_usrp2p()) { _ads62p44_regs.coarse_gain = gain ? ads62p44_regs_t::COARSE_GAIN_3_5DB : ads62p44_regs_t::COARSE_GAIN_0DB; this->send_ads62p44_reg(0x14); } else UHD_THROW_INVALID_CODE_PATH(); diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp index 6065b6c28..1c1f60765 100644 --- a/host/lib/usrp/usrp2/codec_impl.cpp +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -67,7 +67,7 @@ void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ return; case CODEC_PROP_GAIN_NAMES: - if(_iface->get_hw_rev().is_usrp2p()) { + if(_iface->is_usrp2p()) { val = prop_names_t(codec_rx_gain_ranges.keys()); } else val = prop_names_t(); return; @@ -94,7 +94,7 @@ void usrp2_mboard_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val){ switch(key.as()) { case CODEC_PROP_GAIN_I: case CODEC_PROP_GAIN_Q: - if(!_iface->get_hw_rev().is_usrp2p()) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P + if(!_iface->is_usrp2p()) UHD_THROW_PROP_SET_ERROR();//this capability is only found in USRP2P gain = val.as(); this->rx_codec_set_gain(gain, key.name); diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index eb5b79b20..5b9dd1fa3 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -20,7 +20,6 @@ #include #include #include -#include "mboard_rev.hpp" #include #include #include @@ -148,7 +147,7 @@ void usrp2_mboard_impl::update_clock_config(void){ _iface->poke32(_iface->regs.time64_flags, pps_flags); //clock source ref 10mhz - if(_iface->get_hw_rev().is_usrp2p()) { + if(_iface->is_usrp2p()) { switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; @@ -166,7 +165,7 @@ void usrp2_mboard_impl::update_clock_config(void){ //clock source ref 10mhz bool use_external = (_clock_config.ref_source != clock_config_t::REF_INT) - || (_iface->get_hw_rev().is_usrp2p()); //USRP2P has an internal 10MHz TCXO + || (_iface->is_usrp2p()); //USRP2P has an internal 10MHz TCXO _clock_ctrl->enable_external_ref(use_external); } diff --git a/host/lib/usrp/usrp2/mboard_rev.cpp b/host/lib/usrp/usrp2/mboard_rev.cpp deleted file mode 100644 index 9d0ff89f5..000000000 --- a/host/lib/usrp/usrp2/mboard_rev.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// -// 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 "mboard_rev.hpp" -#include -#include -#include -#include - -static const mboard_rev_t usrp2p_first_hw_rev = mboard_rev_t(0x0A00); - -mboard_rev_t::mboard_rev_t(boost::uint16_t rev){ - _rev = rev; -} - -mboard_rev_t mboard_rev_t::none(void){ - return mboard_rev_t(); -} - -mboard_rev_t mboard_rev_t::from_uint16(boost::uint16_t uint16){ - return mboard_rev_t(uint16); -} - -boost::uint16_t mboard_rev_t::to_uint16(void) const{ - return _rev; -} - -//used with lexical cast to parse a hex string -template struct to_hex{ - T value; - operator T() const {return value;} - friend std::istream& operator>>(std::istream& in, to_hex& out){ - in >> std::hex >> out.value; - return in; - } -}; - -mboard_rev_t mboard_rev_t::from_string(const std::string &string){ - if (string.substr(0, 2) == "0x"){ - return mboard_rev_t::from_uint16(boost::lexical_cast >(string)); - } - return mboard_rev_t::from_uint16(boost::lexical_cast(string)); -} - -std::string mboard_rev_t::to_string(void) const{ - return str(boost::format("0x%04x") % this->to_uint16()); -} - -std::string mboard_rev_t::to_pp_string(void) const{ - if(this->is_usrp2p()) { - return str(boost::format("USRP2+, major rev %i, minor rev %i") % int(this->major()) % int(this->minor())); - } else { - return str(boost::format("USRP2, major rev %i, minor rev %i") % int(this->major()) % int(this->minor())); - } -} - -bool mboard_rev_t::is_usrp2p(void) const{ - return _rev >= usrp2p_first_hw_rev; -} - -boost::uint8_t mboard_rev_t::major(void) const{ - return _rev >> 8; -} - -boost::uint8_t mboard_rev_t::minor(void) const{ - return _rev & 0xff; -} - -bool operator==(const mboard_rev_t &lhs, const mboard_rev_t &rhs){ - return lhs.to_uint16() == rhs.to_uint16(); -} - -bool operator<(const mboard_rev_t &lhs, const mboard_rev_t &rhs){ - return lhs.to_uint16() < rhs.to_uint16(); -} diff --git a/host/lib/usrp/usrp2/mboard_rev.hpp b/host/lib/usrp/usrp2/mboard_rev.hpp deleted file mode 100644 index a1b1d9605..000000000 --- a/host/lib/usrp/usrp2/mboard_rev.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// 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 . -// - -#ifndef INCLUDED_MBOARD_REV_HPP -#define INCLUDED_MBOARD_REV_HPP - -#include -#include -#include -#include - -class UHD_API mboard_rev_t : boost::equality_comparable, boost::less_than_comparable{ - public: - /*! - * Create a mboard rev from an integer. - * \param rev the integer representation - */ - mboard_rev_t(boost::uint16_t rev = 0xffff); - - /*! - * Obtain a mboard rev that represents an invalid/uninit mboard ID - * \return the mboard rev with the 0xffff rev. - */ - static mboard_rev_t none(void); - - /*! - * Create a new mboard rev from an integer representation. - * \param uint16 an unsigned 16 bit integer - * \return a new mboard rev containing the integer - */ - static mboard_rev_t from_uint16(boost::uint16_t uint16); - - /*! - * Get the mboard rev represented as an integer. - * \return an unsigned 16 bit integer representation - */ - boost::uint16_t to_uint16(void) const; - - /*! - * Create a new mboard rev from a string representation. - * If the string has a 0x prefix, it will be parsed as hex. - * \param string a numeric string, possibly hex - * \return a new dboard id containing the integer - */ - static mboard_rev_t from_string(const std::string &string); - - /*! - * Get the mboard rev represented as an integer. - * \return a hex string representation with 0x prefix - */ - std::string to_string(void) const; - - /*! - * Get the pretty print representation of this mboard rev. - * \return a string with the mboard name and rev number - */ - std::string to_pp_string(void) const; - - /*! - * Tell you if you're USRP2 or USRP2+ - * \return true if USRP2+, false if USRP2 - */ - bool is_usrp2p(void) const; - - /*! - * Get the major revision number - * \return major revision number - */ - boost::uint8_t major(void) const; - - /*! - * Get the minor revision number - * \return minor revision number - */ - boost::uint8_t minor(void) const; - - private: - boost::uint16_t _rev; //internal representation - }; - - /*! - * Comparator operator overloaded for mboard rev. - * The boost::equality_comparable provides the !=. - * \param lhs the mboard rev to the left of the operator - * \param rhs the mboard rev to the right of the operator - * \return true when the mboard revs are equal - */ - UHD_API bool operator==(const mboard_rev_t &lhs, const mboard_rev_t &rhs); - - /*! - * Comparator operator overloaded for mboard rev. - * The boost::less_than_comparable provides the >, <=, >=. - * \param lhs the mboard rev to the left of the operator - * \param rhs the mboard rev to the right of the operator - * \return true when lhs < rhs - */ - - UHD_API bool operator<(const mboard_rev_t &lhs, const mboard_rev_t &rhs); - -#endif /* INCLUDED_MBOARD_REV_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp index fcfd1e227..d5f80a919 100644 --- a/host/lib/usrp/usrp2/usrp2_clk_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_clk_regs.hpp @@ -18,23 +18,33 @@ #ifndef INCLUDED_USRP2_CLK_REGS_HPP #define INCLUDED_USRP2_CLK_REGS_HPP -#include "mboard_rev.hpp" #include "usrp2_regs.hpp" class usrp2_clk_regs_t { public: usrp2_clk_regs_t(void) { ; } - usrp2_clk_regs_t(mboard_rev_t hw_rev) { + usrp2_clk_regs_t(boost::uint16_t hw_rev) { test = 0; fpga = 1; - adc = (hw_rev.is_usrp2p()) ? 2 : 4; + adc = (hw_rev >= usrp2_rev_nums(N2XX)) ? 2 : 4; dac = 3; - serdes = (hw_rev.is_usrp2p()) ? 4 : 2; //only used by usrp2+ - tx_db = (hw_rev.is_usrp2p()) ? 5 : 6; + serdes = (hw_rev >= usrp2_rev_nums(N2XX)) ? 4 : 2; //only used by usrp2+ + tx_db = (hw_rev >= usrp2_rev_nums(N2XX)) ? 5 : 6; - if(hw_rev.major() == 3) exp = 2; - else if(hw_rev.major() >= 4) exp = 5; - else if(hw_rev.major() > 10) exp = 6; + switch(hw_rev) { + case usrp2_rev_nums(USRP2_REV3): + exp = 2; + break; + case usrp2_rev_nums(USRP2_REV4): + exp = 5; + break; + case usrp2_rev_nums(N2XX): + exp = 6; + break; + default: + throw std::runtime_error("Unknown hardware revision"); + break; + } rx_db = 7; } diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 52adb5373..147b968b4 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -19,7 +19,6 @@ #include "usrp2_iface.hpp" #include #include -#include "mboard_rev.hpp" #include #include #include //used for htonl and ntohl @@ -53,9 +52,8 @@ public: usrp2_iface_impl(udp_simple::sptr ctrl_transport){ _ctrl_transport = ctrl_transport; - //extract the mboard rev numbers - byte_vector_t rev_bytes = read_eeprom(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, 2); - set_hw_rev(mboard_rev_t::from_uint16(rev_bytes.at(0) | (rev_bytes.at(1) << 8))); + mb_eeprom = mboard_eeprom_t(*this, mboard_eeprom_t::MAP_N100); + regs = usrp2_get_regs(get_hw_rev()); //check the fpga compatibility number const boost::uint32_t fpga_compat_num = this->peek32(this->regs.compat_num_rb); @@ -65,8 +63,6 @@ public: "The fpga build is not compatible with the host code build." ) % int(USRP2_FPGA_COMPAT_NUM) % fpga_compat_num)); } - - mb_eeprom = mboard_eeprom_t(*this, mboard_eeprom_t::MAP_N100); } ~usrp2_iface_impl(void){ @@ -263,17 +259,13 @@ public: } throw std::runtime_error("usrp2 no control response"); } - - /*********************************************************************** - * Get/set hardware revision - **********************************************************************/ - void set_hw_rev(mboard_rev_t rev) { - hw_rev = rev; - regs = usrp2_get_regs(rev); //might be a better place to do this + + bool is_usrp2p(void) { + return (get_hw_rev() >= usrp2_rev_nums(N2XX)); } - - mboard_rev_t get_hw_rev(void) { - return hw_rev; + + boost::uint16_t get_hw_rev(void) { + return boost::lexical_cast(mb_eeprom["rev"]); } @@ -313,7 +305,6 @@ private: UHD_ASSERT_THROW(ntohl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE); return T(ntohl(in_data.data.poke_args.data)); } - }; /*********************************************************************** @@ -322,3 +313,4 @@ private: usrp2_iface::sptr usrp2_iface::make(udp_simple::sptr ctrl_transport){ return usrp2_iface::sptr(new usrp2_iface_impl(ctrl_transport)); } + diff --git a/host/lib/usrp/usrp2/usrp2_iface.hpp b/host/lib/usrp/usrp2/usrp2_iface.hpp index 88bff5913..d7e5df9f5 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.hpp +++ b/host/lib/usrp/usrp2/usrp2_iface.hpp @@ -24,7 +24,6 @@ #include #include #include -#include "mboard_rev.hpp" #include #include "fw_common.h" #include "usrp2_regs.hpp" @@ -109,26 +108,16 @@ public: virtual void write_uart(boost::uint8_t dev, const std::string &buf) = 0; virtual std::string read_uart(boost::uint8_t dev) = 0; - - /*! - * Set the hardware revision number. Also selects the proper register set for the device. - * \param rev the 16-bit revision - */ - virtual void set_hw_rev(mboard_rev_t rev) = 0; - - /*! Return the hardware revision number - * \return hardware revision - */ - virtual mboard_rev_t get_hw_rev(void) = 0; + + virtual boost::uint16_t get_hw_rev(void) = 0; + + virtual bool is_usrp2p(void) = 0; /*! * Register map selected from USRP2/USRP2+. */ usrp2_regs_t regs; - /*! - * Hardware revision as returned by the device. - */ - mboard_rev_t hw_rev; + //motherboard eeprom map structure uhd::usrp::mboard_eeprom_t mb_eeprom; }; diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp index 0f0360c95..5853e91e5 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.cpp +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -15,25 +15,23 @@ // along with this program. If not, see . // -#include "mboard_rev.hpp" #include "usrp2_regs.hpp" int sr_addr(int misc_output_base, int sr) { return misc_output_base + 4 * sr; } -usrp2_regs_t usrp2_get_regs(mboard_rev_t hw_rev) { - +usrp2_regs_t usrp2_get_regs(boost::uint16_t hw_rev) { //how about you just make this dependent on hw_rev instead of doing the init before main, and give up the const globals, since the application won't ever need both. - const int misc_output_base = (hw_rev.is_usrp2p()) ? USRP2P_MISC_OUTPUT_BASE : USRP2_MISC_OUTPUT_BASE, - gpio_base = (hw_rev.is_usrp2p()) ? USRP2P_GPIO_BASE : USRP2_GPIO_BASE, - atr_base = (hw_rev.is_usrp2p()) ? USRP2P_ATR_BASE : USRP2_ATR_BASE, - bp_base = (hw_rev.is_usrp2p()) ? USRP2P_BP_STATUS_BASE : USRP2_BP_STATUS_BASE; + const int misc_output_base = (hw_rev >= usrp2_rev_nums(N2XX)) ? USRP2P_MISC_OUTPUT_BASE : USRP2_MISC_OUTPUT_BASE, + gpio_base = (hw_rev >= usrp2_rev_nums(N2XX)) ? USRP2P_GPIO_BASE : USRP2_GPIO_BASE, + atr_base = (hw_rev >= usrp2_rev_nums(N2XX)) ? USRP2P_ATR_BASE : USRP2_ATR_BASE, + bp_base = (hw_rev >= usrp2_rev_nums(N2XX)) ? USRP2P_BP_STATUS_BASE : USRP2_BP_STATUS_BASE; usrp2_regs_t x; x.sr_misc = 0; x.sr_tx_prot_eng = 32; - x.sr_rx_prot_eng = 48; + x.sr_rx_prot_eng = 48; x.sr_buffer_pool_ctrl = 64; x.sr_udp_sm = 96; x.sr_tx_dsp = 208; diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 0d68c65c2..d84106f36 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -18,7 +18,13 @@ #ifndef INCLUDED_USRP2_REGS_HPP #define INCLUDED_USRP2_REGS_HPP -#include "mboard_rev.hpp" +#include + +enum usrp2_rev_nums { + USRP2_REV3 = 0x0003, + USRP2_REV4 = 0x0004, + N2XX = 0x0A00 +}; #define USRP2_MISC_OUTPUT_BASE 0xD400 #define USRP2_GPIO_BASE 0xC800 @@ -30,80 +36,78 @@ #define USRP2P_ATR_BASE 0x3800 #define USRP2P_BP_STATUS_BASE 0x3300 -const mboard_rev_t USRP2P_FIRST_HW_REV(0x0A00); - typedef struct { - int sr_misc; - int sr_tx_prot_eng; - int sr_rx_prot_eng; - int sr_buffer_pool_ctrl; - int sr_udp_sm; - int sr_tx_dsp; - int sr_tx_ctrl; - int sr_rx_dsp; - int sr_rx_ctrl; - int sr_time64; - int sr_simtimer; - int sr_last; - int misc_ctrl_clock; - int misc_ctrl_serdes; - int misc_ctrl_adc; - int misc_ctrl_leds; - int misc_ctrl_phy; - int misc_ctrl_dbg_mux; - int misc_ctrl_ram_page; - int misc_ctrl_flush_icache; - int misc_ctrl_led_src; - int time64_secs; // value to set absolute secs to on next PPS - int time64_ticks; // value to set absolute ticks to on next PPS - int time64_flags; // flags -- see chart below - int time64_imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0) - int time64_tps; // ticks per second rollover count - int time64_secs_rb; - int time64_ticks_rb; - int compat_num_rb; - int dsp_tx_freq; - int dsp_tx_scale_iq; - int dsp_tx_interp_rate; - int dsp_tx_mux; - int dsp_rx_freq; - int dsp_rx_scale_iq; - int dsp_rx_decim_rate; - int dsp_rx_dcoffset_i; - int dsp_rx_dcoffset_q; - int dsp_rx_mux; - int gpio_base; - int gpio_io; - int gpio_ddr; - int gpio_tx_sel; - int gpio_rx_sel; - int atr_base; - int atr_idle_txside; - int atr_idle_rxside; - int atr_intx_txside; - int atr_intx_rxside; - int atr_inrx_txside; - int atr_inrx_rxside; - int atr_full_txside; - int atr_full_rxside; - int rx_ctrl_stream_cmd; - int rx_ctrl_time_secs; - int rx_ctrl_time_ticks; - int rx_ctrl_clear_overrun; - int rx_ctrl_vrt_header; - int rx_ctrl_vrt_stream_id; - int rx_ctrl_vrt_trailer; - int rx_ctrl_nsamps_per_pkt; - int rx_ctrl_nchannels; - int tx_ctrl_num_chan; - int tx_ctrl_clear_state; - int tx_ctrl_report_sid; - int tx_ctrl_policy; + int sr_misc; + int sr_tx_prot_eng; + int sr_rx_prot_eng; + int sr_buffer_pool_ctrl; + int sr_udp_sm; + int sr_tx_dsp; + int sr_tx_ctrl; + int sr_rx_dsp; + int sr_rx_ctrl; + int sr_time64; + int sr_simtimer; + int sr_last; + int misc_ctrl_clock; + int misc_ctrl_serdes; + int misc_ctrl_adc; + int misc_ctrl_leds; + int misc_ctrl_phy; + int misc_ctrl_dbg_mux; + int misc_ctrl_ram_page; + int misc_ctrl_flush_icache; + int misc_ctrl_led_src; + int time64_secs; // value to set absolute secs to on next PPS + int time64_ticks; // value to set absolute ticks to on next PPS + int time64_flags; // flags -- see chart below + int time64_imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0) + int time64_tps; // ticks per second rollover count + int time64_secs_rb; + int time64_ticks_rb; + int compat_num_rb; + int dsp_tx_freq; + int dsp_tx_scale_iq; + int dsp_tx_interp_rate; + int dsp_tx_mux; + int dsp_rx_freq; + int dsp_rx_scale_iq; + int dsp_rx_decim_rate; + int dsp_rx_dcoffset_i; + int dsp_rx_dcoffset_q; + int dsp_rx_mux; + int gpio_base; + int gpio_io; + int gpio_ddr; + int gpio_tx_sel; + int gpio_rx_sel; + int atr_base; + int atr_idle_txside; + int atr_idle_rxside; + int atr_intx_txside; + int atr_intx_rxside; + int atr_inrx_txside; + int atr_inrx_rxside; + int atr_full_txside; + int atr_full_rxside; + int rx_ctrl_stream_cmd; + int rx_ctrl_time_secs; + int rx_ctrl_time_ticks; + int rx_ctrl_clear_overrun; + int rx_ctrl_vrt_header; + int rx_ctrl_vrt_stream_id; + int rx_ctrl_vrt_trailer; + int rx_ctrl_nsamps_per_pkt; + int rx_ctrl_nchannels; + int tx_ctrl_num_chan; + int tx_ctrl_clear_state; + int tx_ctrl_report_sid; + int tx_ctrl_policy; } usrp2_regs_t; extern const usrp2_regs_t usrp2_regs; //the register definitions, set in usrp2_regs.cpp and usrp2p_regs.cpp -usrp2_regs_t usrp2_get_regs(mboard_rev_t hw_rev); +usrp2_regs_t usrp2_get_regs(boost::uint16_t hw_rev); //////////////////////////////////////////////////// // Settings Bus, Slave #7, Not Byte Addressable! -- cgit v1.2.3