diff options
Diffstat (limited to 'firmware')
25 files changed, 580 insertions, 1761 deletions
diff --git a/firmware/zpu/apps/blinkenlights.c b/firmware/zpu/apps/blinkenlights.c deleted file mode 100644 index 30cb33a7f..000000000 --- a/firmware/zpu/apps/blinkenlights.c +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 Ettus Research LLC - * - */ - -#include "memory_map.h" -#include <nonstdio.h> - -int main(int argc, char *argv[]) { - - uint32_t c = 0; - uint8_t i = 0; - - output_regs->led_src = 0; - - while(1) { - //delay(5000000); - for(c=0;c<50000;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/zpu/apps/flash_test.c b/firmware/zpu/apps/flash_test.c deleted file mode 100644 index 5b4569030..000000000 --- a/firmware/zpu/apps/flash_test.c +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 Ettus Research LLC - * - */ - -#include <memory_map.h> -#include <hal_io.h> -#include <hal_uart.h> -#include <xilinx_s3_icap.h> -#include <nonstdio.h> -#include <spi_flash.h> -#include <spi.h> -#include <clocks.h> -#include <string.h> - -//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/zpu/apps/hardware_testbed.c b/firmware/zpu/apps/hardware_testbed.c deleted file mode 100644 index e68e68ff7..000000000 --- a/firmware/zpu/apps/hardware_testbed.c +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 Ettus Research LLC - * - */ - -#include <memory_map.h> -#include <nonstdio.h> -#include <hal_io.h> -#include <xilinx_s3_icap.h> -#include <spi_flash.h> -//#include <spi_flash_private.h> -#include <clocks.h> -#include <ihex.h> -#include <bootloader_utils.h> -#include <string.h> -#include <hal_uart.h> -#include <spi.h> - -//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/zpu/apps/txrx_uhd.c b/firmware/zpu/apps/txrx_uhd.c index 68c24e872..975ec58e2 100644 --- a/firmware/zpu/apps/txrx_uhd.c +++ b/firmware/zpu/apps/txrx_uhd.c @@ -1,8 +1,5 @@ -// -// Copyright 2010-2011 Ettus Research LLC -// /* - * Copyright 2007,2008 Free Software Foundation, Inc. + * Copyright 2010-2011 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 @@ -18,94 +15,65 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <lwip/ip.h> -#include <lwip/udp.h> +//peripheral headers #include "u2_init.h" -#include "memory_map.h" #include "spi.h" +#include "i2c.h" #include "hal_io.h" #include "pic.h" -#include <stdbool.h> -#include "ethernet.h" + +//printf headers #include "nonstdio.h" -#include <net/padded_eth_hdr.h> -#include <net_common.h> -#include "memcpy_wa.h" -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include "clocks.h" + +//network headers +#include "arp_cache.h" +#include "ethernet.h" +#include "net_common.h" #include "usrp2/fw_common.h" -#include <i2c.h> -#include <ethertype.h> -#include <arp_cache.h> #include "udp_fw_update.h" #include "pkt_ctrl.h" -#include "banal.h" -static void setup_network(void); +//standard headers +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#ifdef BOOTLOADER +#include <bootloader_utils.h> +#endif + +//virtual registers in the firmware to store persistent values +static uint32_t fw_regs[8]; -// ---------------------------------------------------------------- -// the fast-path setup global variables -// ---------------------------------------------------------------- -static eth_mac_addr_t fp_mac_addr_src, fp_mac_addr_dst; -struct socket_address fp_socket_src, fp_socket_dst; extern uint16_t dsp0_dst_port, err0_dst_port, dsp1_dst_port; -static void handle_udp_err0_packet( +static void handle_udp_data_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ - sr_udp_sm->err0_port = (((uint32_t)dst.port) << 16) | src.port; - err0_dst_port = src.port; - printf("Storing for async error path:\n"); - printf(" source udp port: %d\n", dst.port); - printf(" destination udp port: %d\n", src.port); - newline(); -} + size_t which; + switch(dst.port){ + case USRP2_UDP_DSP0_PORT: + which = 0; + dsp0_dst_port = src.port; + break; -static void handle_udp_dsp1_packet( - struct socket_address src, struct socket_address dst, - unsigned char *payload, int payload_len -){ - sr_udp_sm->dsp1_port = (((uint32_t)dst.port) << 16) | src.port; - dsp1_dst_port = src.port; - printf("Storing for dsp1 path:\n"); - printf(" source udp port: %d\n", dst.port); - printf(" destination udp port: %d\n", src.port); - newline(); -} + case USRP2_UDP_DSP1_PORT: + which = 2; + dsp1_dst_port = src.port; + break; -static void handle_udp_dsp0_packet( - struct socket_address src, struct socket_address dst, - unsigned char *payload, int payload_len -){ - fp_mac_addr_src = *ethernet_mac_addr(); - arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst); - fp_socket_src = dst; - fp_socket_dst = src; - sr_udp_sm->dsp0_port = (((uint32_t)dst.port) << 16) | src.port; - dsp0_dst_port = src.port; - printf("Storing for dsp0 path:\n"); - printf(" source mac addr: "); - print_mac_addr(&fp_mac_addr_src); newline(); - printf(" source ip addr: "); - print_ip_addr(&fp_socket_src.addr); newline(); - printf(" source udp port: %d\n", fp_socket_src.port); - printf(" destination mac addr: "); - print_mac_addr(&fp_mac_addr_dst); newline(); - printf(" destination ip addr: "); - print_ip_addr(&fp_socket_dst.addr); newline(); - printf(" destination udp port: %d\n", fp_socket_dst.port); - newline(); - - //setup network - setup_network(); + case USRP2_UDP_ERR0_PORT: + which = 1; + err0_dst_port = src.port; + break; + default: return; + } + + eth_mac_addr_t eth_mac_host; arp_cache_lookup_mac(&src.addr, ð_mac_host); + setup_framer(eth_mac_host, *ethernet_mac_addr(), src, dst, which); } #define OTW_GPIO_BANK_TO_NUM(bank) \ @@ -202,40 +170,34 @@ static void handle_udp_ctrl_packet( /******************************************************************* * Peek and Poke Register ******************************************************************/ - case USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO: - switch(ctrl_data_in->data.poke_args.num_bytes){ - case sizeof(uint32_t): - *((uint32_t *) ctrl_data_in->data.poke_args.addr) = (uint32_t)ctrl_data_in->data.poke_args.data; - break; - - case sizeof(uint16_t): - *((uint16_t *) ctrl_data_in->data.poke_args.addr) = (uint16_t)ctrl_data_in->data.poke_args.data; - break; + case USRP2_CTRL_ID_GET_THIS_REGISTER_FOR_ME_BRO: + switch(ctrl_data_in->data.reg_args.action){ + case USRP2_REG_ACTION_FPGA_PEEK32: + ctrl_data_out.data.reg_args.data = *((uint32_t *) ctrl_data_in->data.reg_args.addr); + break; - case sizeof(uint8_t): - *((uint8_t *) ctrl_data_in->data.poke_args.addr) = (uint8_t)ctrl_data_in->data.poke_args.data; - break; + case USRP2_REG_ACTION_FPGA_PEEK16: + ctrl_data_out.data.reg_args.data = *((uint16_t *) ctrl_data_in->data.reg_args.addr); + break; - } - ctrl_data_out.id = USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE; - break; + case USRP2_REG_ACTION_FPGA_POKE32: + *((uint32_t *) ctrl_data_in->data.reg_args.addr) = (uint32_t)ctrl_data_in->data.reg_args.data; + break; - case USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO: - switch(ctrl_data_in->data.poke_args.num_bytes){ - case sizeof(uint32_t): - ctrl_data_out.data.poke_args.data = *((uint32_t *) ctrl_data_in->data.poke_args.addr); - break; + case USRP2_REG_ACTION_FPGA_POKE16: + *((uint16_t *) ctrl_data_in->data.reg_args.addr) = (uint16_t)ctrl_data_in->data.reg_args.data; + break; - case sizeof(uint16_t): - ctrl_data_out.data.poke_args.data = *((uint16_t *) ctrl_data_in->data.poke_args.addr); - break; + case USRP2_REG_ACTION_FW_PEEK32: + ctrl_data_out.data.reg_args.data = fw_regs[(ctrl_data_in->data.reg_args.addr)]; + break; - case sizeof(uint8_t): - ctrl_data_out.data.poke_args.data = *((uint8_t *) ctrl_data_in->data.poke_args.addr); - break; + case USRP2_REG_ACTION_FW_POKE32: + fw_regs[(ctrl_data_in->data.reg_args.addr)] = ctrl_data_in->data.reg_args.data; + break; } - ctrl_data_out.id = USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE; + ctrl_data_out.id = USRP2_CTRL_ID_OMG_GOT_REGISTER_SO_BAD_DUDE; break; /******************************************************************* @@ -278,6 +240,7 @@ static void handle_udp_ctrl_packet( send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); } +#include <net/padded_eth_hdr.h> static void handle_inp_packet(uint32_t *buff, size_t num_lines){ //test if its an ip recovery packet @@ -299,7 +262,6 @@ static void handle_inp_packet(uint32_t *buff, size_t num_lines){ handle_eth_packet(buff, num_lines); } - //------------------------------------------------------------------ /* @@ -318,50 +280,28 @@ void link_changed_callback(int speed){ } } -static void setup_network(void){ - - //setup ethernet header machine - sr_udp_sm->eth_hdr.mac_dst_0_1 = (fp_mac_addr_dst.addr[0] << 8) | fp_mac_addr_dst.addr[1]; - sr_udp_sm->eth_hdr.mac_dst_2_3 = (fp_mac_addr_dst.addr[2] << 8) | fp_mac_addr_dst.addr[3]; - sr_udp_sm->eth_hdr.mac_dst_4_5 = (fp_mac_addr_dst.addr[4] << 8) | fp_mac_addr_dst.addr[5]; - sr_udp_sm->eth_hdr.mac_src_0_1 = (fp_mac_addr_src.addr[0] << 8) | fp_mac_addr_src.addr[1]; - sr_udp_sm->eth_hdr.mac_src_2_3 = (fp_mac_addr_src.addr[2] << 8) | fp_mac_addr_src.addr[3]; - sr_udp_sm->eth_hdr.mac_src_4_5 = (fp_mac_addr_src.addr[4] << 8) | fp_mac_addr_src.addr[5]; - sr_udp_sm->eth_hdr.ether_type = ETHERTYPE_IPV4; - - //setup ip header machine - unsigned int chksum = 0; - sr_udp_sm->ip_hdr.ver_ihl_tos = CHKSUM(0x4500, &chksum); // IPV4, 5 words of header (20 bytes), TOS=0 - sr_udp_sm->ip_hdr.total_length = UDP_SM_INS_IP_LEN; // Don't checksum this line in SW - sr_udp_sm->ip_hdr.identification = CHKSUM(0x0000, &chksum); // ID - sr_udp_sm->ip_hdr.flags_frag_off = CHKSUM(0x4000, &chksum); // don't fragment - sr_udp_sm->ip_hdr.ttl_proto = CHKSUM(0x2011, &chksum); // TTL=32, protocol = UDP (17 decimal) - //sr_udp_sm->ip_hdr.checksum .... filled in below - uint32_t src_ip_addr = fp_socket_src.addr.addr; - uint32_t dst_ip_addr = fp_socket_dst.addr.addr; - sr_udp_sm->ip_hdr.src_addr_high = CHKSUM(src_ip_addr >> 16, &chksum); // IP src high - sr_udp_sm->ip_hdr.src_addr_low = CHKSUM(src_ip_addr & 0xffff, &chksum); // IP src low - sr_udp_sm->ip_hdr.dst_addr_high = CHKSUM(dst_ip_addr >> 16, &chksum); // IP dst high - sr_udp_sm->ip_hdr.dst_addr_low = CHKSUM(dst_ip_addr & 0xffff, &chksum); // IP dst low - sr_udp_sm->ip_hdr.checksum = UDP_SM_INS_IP_HDR_CHKSUM | (chksum & 0xffff); - - //setup the udp header machine - sr_udp_sm->udp_hdr.src_port = UDP_SM_INS_UDP_SRC_PORT; - sr_udp_sm->udp_hdr.dst_port = UDP_SM_INS_UDP_DST_PORT; - sr_udp_sm->udp_hdr.length = UDP_SM_INS_UDP_LEN; - sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum -} - int main(void) { u2_init(); - +#ifdef BOOTLOADER + putstr("\nUSRP N210 UDP bootloader\n"); +#else putstr("\nTxRx-UHD-ZPU\n"); - print_mac_addr(ethernet_mac_addr()); newline(); - print_ip_addr(get_ip_addr()); newline(); +#endif printf("FPGA compatibility number: %d\n", USRP2_FPGA_COMPAT_NUM); printf("Firmware compatibility number: %d\n", USRP2_FW_COMPAT_NUM); + +#ifdef BOOTLOADER + //load the production FPGA image or firmware if appropriate + do_the_bootload_thing(); + //if we get here we've fallen through to safe firmware + set_default_mac_addr(); + set_default_ip_addr(); +#endif + + print_mac_addr(ethernet_mac_addr()); newline(); + print_ip_addr(get_ip_addr()); newline(); //1) register the addresses into the network stack register_addrs(ethernet_mac_addr(), get_ip_addr()); @@ -370,9 +310,9 @@ main(void) //2) register callbacks for udp ports we service init_udp_listeners(); register_udp_listener(USRP2_UDP_CTRL_PORT, handle_udp_ctrl_packet); - register_udp_listener(USRP2_UDP_DSP0_PORT, handle_udp_dsp0_packet); - register_udp_listener(USRP2_UDP_ERR0_PORT, handle_udp_err0_packet); - register_udp_listener(USRP2_UDP_DSP1_PORT, handle_udp_dsp1_packet); + register_udp_listener(USRP2_UDP_DSP0_PORT, handle_udp_data_packet); + register_udp_listener(USRP2_UDP_ERR0_PORT, handle_udp_data_packet); + register_udp_listener(USRP2_UDP_DSP1_PORT, handle_udp_data_packet); #ifdef USRP2P register_udp_listener(USRP2_UDP_UPDATE_PORT, handle_udp_fw_update_packet); #endif diff --git a/firmware/zpu/apps/uart_flash_loader.c b/firmware/zpu/apps/uart_flash_loader.c deleted file mode 100644 index 4ec89284a..000000000 --- a/firmware/zpu/apps/uart_flash_loader.c +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 Ettus Research LLC - * - */ - -//#include <stdio.h> -#include <stdlib.h> -#include <memory_map.h> -#include <nonstdio.h> -#include <hal_io.h> -#include <hal_uart.h> -#include <xilinx_s3_icap.h> -#include <spi_flash.h> -#include <spi_flash_private.h> -//#include <clocks.h> -#include <ihex.h> -#include <bootloader_utils.h> - -//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/zpu/bin/bin_to_ram_macro_init.py b/firmware/zpu/bin/bin_to_ram_macro_init.py index 085045290..bf8abb19a 100755 --- a/firmware/zpu/bin/bin_to_ram_macro_init.py +++ b/firmware/zpu/bin/bin_to_ram_macro_init.py @@ -3,6 +3,8 @@ import struct import sys +BOOTRAM_SIZE = 16384 + 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" % ( @@ -21,25 +23,13 @@ def bin_to_ram_macro_init(bin_input_file, ram_init_output_file): 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,)) + if len(words) > (BOOTRAM_SIZE / 4): + sys.stderr.write("bin_to_macro_init: error: input file %s is > %dKiB\n" % (bin_input_file,BOOTRAM_SIZE)) 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]) + for q in range(0, BOOTRAM_SIZE/4, 512): + for i in range(q, min(q+512, len(words)), 8): + do_8_words(ofile, int(q / 512), (i/8) % 64, words[i:i+8]) if __name__ == '__main__': if len(sys.argv) != 3: diff --git a/firmware/zpu/lib/eth_mac_regs.h b/firmware/zpu/lib/eth_mac_regs.h deleted file mode 100644 index d680f8de0..000000000 --- a/firmware/zpu/lib/eth_mac_regs.h +++ /dev/null @@ -1,62 +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 <http://www.gnu.org/licenses/>. - */ - -#ifndef INCLUDED_ETH_MAC_REGS_H -#define INCLUDED_ETH_MAC_REGS_H - -/* - * Simple GEMAC - * - */ -typedef struct { - volatile int settings; - volatile int ucast_hi; - volatile int ucast_lo; - volatile int mcast_hi; - volatile int mcast_lo; - volatile int miimoder; - volatile int miiaddress; - volatile int miitx_data; - volatile int miicommand; - volatile int miistatus; - volatile int miirx_data; - volatile int pause_time; - volatile int pause_thresh; -} eth_mac_regs_t; - -// settings register -#define MAC_SET_PAUSE_EN (1 << 0) // Makes us respect received pause frames (normally on) -#define MAC_SET_PASS_ALL (1 << 1) // Enables promiscuous mode, currently broken -#define MAC_SET_PASS_PAUSE (1 << 2) // Sends pause frames through (normally off) -#define MAC_SET_PASS_BCAST (1 << 3) // Sends broadcast frames through (normally on) -#define MAC_SET_PASS_MCAST (1 << 4) // Sends multicast frames that match mcast addr (normally off) -#define MAC_SET_PASS_UCAST (1 << 5) // Sends unicast (normal) frames through if they hit in address filter (normally on) -#define MAC_SET_PAUSE_SEND_EN (1 << 6) // Enables sending pause frames - -// miicommand register -#define MIIC_SCANSSTAT (1 << 0) // Scan status -#define MIIC_RSTAT (1 << 1) // Read status -#define MIIC_WCTRLDATA (1 << 2) // Write control data - -// miistatus register -#define MIIS_LINKFAIL (1 << 0) // The link failed -#define MIIS_BUSY (1 << 1) // The MII is busy (operation in progress) -#define MIIS_NVALID (1 << 2) // The data in the status register is invalid - // This it is only valid when the scan status is active. - -#endif /* INCLUDED_ETH_MAC_REGS_H */ diff --git a/firmware/zpu/usrp2p/memory_map.h b/firmware/zpu/lib/memory_map.h index 2567a4588..938cf7776 100644 --- a/firmware/zpu/usrp2p/memory_map.h +++ b/firmware/zpu/lib/memory_map.h @@ -21,34 +21,33 @@ #include <stdint.h> - -#define MASTER_CLK_RATE 100000000 // 100 MHz - - -//////////////////////////////////////////////////////////////// -// -// Memory map for embedded wishbone bus -// -//////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////// -// Boot RAM, Slave 0 - -#define BOOTRAM_BASE 0x0000 - - -//////////////////////////////////////////////////////////////// -// Packet Router RAM, Slave 1 -// -// The buffers themselves are located in Slave 1, Packet Router RAM. -// The status registers are in Slave 5, Packet Router Status. -// The control register is in Slave 7, Settings Bus. - -#define ROUTER_RAM_BASE 0x4000 +#define MASTER_CLK_RATE 100000000 // 100 MHz + +//////////////////////////////////////////////////////////////////////// +// Define slave bases +//////////////////////////////////////////////////////////////////////// +#define ROUTER_RAM_BASE 0x4000 +#define SPI_BASE 0x5000 +#define I2C_BASE 0x5400 +#define GPIO_BASE 0x5800 +#define READBACK_BASE 0x5C00 +#define ETH_BASE 0x6000 +#define SETTING_REGS_BASE 0x7000 +#define PIC_BASE 0x8000 +#define UART_BASE 0x8800 +#define ATR_BASE 0x8C00 +#ifdef USRP2 +#define SDSPI_BASE 0xB000 +#endif +#ifdef USRP2P +#define ICAP_BASE 0xA000 +#define SPIF_BASE 0xB000 +#define RAM_BASE 0xC000 +#endif ///////////////////////////////////////////////////// // SPI Core, Slave 2. See core docs for more info -#define SPI_BASE 0x6000 // Base address (16-bit) is base peripheral addr +///////////////////////////////////////////////////// typedef struct { volatile uint32_t txrx0; @@ -62,7 +61,6 @@ typedef struct { #define spi_regs ((spi_regs_t *) SPI_BASE) - // Masks for controlling different peripherals #define SPI_SS_AD9510 1 #define SPI_SS_AD9777 2 @@ -85,9 +83,7 @@ typedef struct { //////////////////////////////////////////////// // I2C, Slave 3 -// See Wishbone I2C-Master Core Specification. - -#define I2C_BASE 0x6100 +//////////////////////////////////////////////// typedef struct { volatile uint32_t prescaler_lo; // r/w @@ -123,37 +119,9 @@ typedef struct { #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 0x6200 - -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) - /////////////////////////////////////////////////// // Packet Router Status, Slave 5 -// -// The buffers themselves are located in Slave 1, Packet Router RAM. -// The status registers are in Slave 5, Packet Router Status. -// The control register is in Slave 7, Settings Bus. - -#define ROUTER_STATUS_BASE 0x6300 +/////////////////////////////////////////////////// typedef struct { volatile uint32_t _padding[8]; @@ -165,9 +133,7 @@ typedef struct { volatile uint32_t irqs; } router_status_t; -#define router_status ((router_status_t *) ROUTER_STATUS_BASE) - -#define BUTTON_PUSHED ((router_status->irqs & PIC_BUTTON) ? 0 : 1) +#define router_status ((router_status_t *) READBACK_BASE) // The hw_config register @@ -195,10 +161,43 @@ hwconfig_wishbone_divisor(void) /////////////////////////////////////////////////// // Ethernet Core, Slave 6 +/////////////////////////////////////////////////// -#define ETH_BASE 0x6400 - -#include "eth_mac_regs.h" +typedef struct { + volatile int settings; + volatile int ucast_hi; + volatile int ucast_lo; + volatile int mcast_hi; + volatile int mcast_lo; + volatile int miimoder; + volatile int miiaddress; + volatile int miitx_data; + volatile int miicommand; + volatile int miistatus; + volatile int miirx_data; + volatile int pause_time; + volatile int pause_thresh; +} eth_mac_regs_t; + +// settings register +#define MAC_SET_PAUSE_EN (1 << 0) // Makes us respect received pause frames (normally on) +#define MAC_SET_PASS_ALL (1 << 1) // Enables promiscuous mode, currently broken +#define MAC_SET_PASS_PAUSE (1 << 2) // Sends pause frames through (normally off) +#define MAC_SET_PASS_BCAST (1 << 3) // Sends broadcast frames through (normally on) +#define MAC_SET_PASS_MCAST (1 << 4) // Sends multicast frames that match mcast addr (normally off) +#define MAC_SET_PASS_UCAST (1 << 5) // Sends unicast (normal) frames through if they hit in address filter (normally on) +#define MAC_SET_PAUSE_SEND_EN (1 << 6) // Enables sending pause frames + +// miicommand register +#define MIIC_SCANSSTAT (1 << 0) // Scan status +#define MIIC_RSTAT (1 << 1) // Read status +#define MIIC_WCTRLDATA (1 << 2) // Write control data + +// miistatus register +#define MIIS_LINKFAIL (1 << 0) // The link failed +#define MIIS_BUSY (1 << 1) // The MII is busy (operation in progress) +#define MIIS_NVALID (1 << 2) // The data in the status register is invalid + // This it is only valid when the scan status is active. #define eth_mac ((eth_mac_regs_t *) ETH_BASE) @@ -207,26 +206,26 @@ hwconfig_wishbone_divisor(void) // // Output-only from processor point-of-view. // 1KB of address space (== 256 32-bit write-only regs) +//////////////////////////////////////////////////// + +#define SR_MISC 0 // 7 regs +#define SR_SIMTIMER 8 // 2 +#define SR_TIME64 10 // 6 +#define SR_BUF_POOL 16 // 4 +#define SR_RX_FRONT 24 // 5 +#define SR_RX_CTRL0 32 // 9 +#define SR_RX_DSP0 48 // 7 +#define SR_RX_CTRL1 80 // 9 +#define SR_RX_DSP1 96 // 7 -#define MISC_OUTPUT_BASE 0x5000 +#define SR_TX_FRONT 128 // ? +#define SR_TX_CTRL 144 // 6 +#define SR_TX_DSP 160 // 5 -#define SR_MISC 0 -#define SR_TX_PROT_ENG 32 -#define SR_RX_PROT_ENG 48 -#define SR_ROUTER_CTRL 64 -#define SR_UDP_SM 96 -#define SR_TX_DSP 208 -#define SR_TX_CTRL 224 -#define SR_RX_DSP0 160 -#define SR_RX_DSP1 240 -#define SR_RX_CTRL0 176 -#define SR_RX_CTRL1 32 -#define SR_TIME64 192 -#define SR_SIMTIMER 198 -#define SR_LAST 255 +#define SR_UDP_SM 192 // 64 -#define _SR_ADDR(sr) (MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t)) +#define _SR_ADDR(sr) (SETTING_REGS_BASE + (sr) * sizeof(uint32_t)) #define SR_ADDR_BLDRDONE _SR_ADDR(5) @@ -239,20 +238,19 @@ typedef struct { volatile uint32_t iface_ctrl; } router_ctrl_t; -#define router_ctrl ((router_ctrl_t *) _SR_ADDR(SR_ROUTER_CTRL)) +#define router_ctrl ((router_ctrl_t *) _SR_ADDR(SR_BUF_POOL)) // --- 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 + 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 led_src; // HW or SW control for LEDs + volatile uint32_t flush_icache; // Flush the icache } output_regs_t; #define CLK_RESET (1<<4) @@ -277,73 +275,17 @@ typedef struct { // LED_F // controlled by CPLD #define LED_RJ45 (1 << 5) -#define output_regs ((output_regs_t *) MISC_OUTPUT_BASE) +#define output_regs ((output_regs_t *) SETTING_REGS_BASE) -// --- udp tx regs --- +// --- protocol framer 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[1]; - volatile uint32_t dsp0_port; - volatile uint32_t err0_port; - volatile uint32_t dsp1_port; - volatile uint32_t err1_port; -} sr_udp_sm_t; - -// control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) - -// Insert a UDP source port from the table -#define UDP_SM_INS_UDP_SRC_PORT (1 << 21) - -// Insert a UDP dest port from the table -#define UDP_SM_INS_UDP_DST_PORT (1 << 20) - -// 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)) +typedef struct{ + struct{ + volatile uint32_t entry[16]; + } table[4]; +} sr_proto_framer_t; + +#define sr_proto_framer_regs ((sr_proto_framer_t *) _SR_ADDR(SR_UDP_SM)) // --- VITA TX CTRL regs --- @@ -397,66 +339,9 @@ typedef struct { #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 *) _SR_ADDR(SR_TX_PROT_ENG)) - -/* - * --- 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 *) _SR_ADDR(SR_RX_PROT_ENG)) - - - -/////////////////////////////////////////////////// +/////////////////////////////////////////////////////// // Simple Programmable Interrupt Controller, Slave 8 - -#define PIC_BASE 0x6500 +/////////////////////////////////////////////////////// // Interrupt request lines // Bit numbers (LSB == 0) that correpond to interrupts into PIC @@ -511,12 +396,8 @@ typedef struct { #define sr_simple_timer ((sr_simple_timer_t *) _SR_ADDR(SR_SIMTIMER)) /////////////////////////////////////////////////// -// UNUSED, Slave 9 - -/////////////////////////////////////////////////// // UART, Slave 10 - -#define UART_BASE 0x6700 +/////////////////////////////////////////////////// typedef struct { // All elements are 8 bits except for clkdiv (16), but we use uint32 to make @@ -526,34 +407,32 @@ 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 ((uart_regs_t *) UART_BASE) /////////////////////////////////////////////////// -// ATR Controller, Slave 11 - -#define ATR_BASE 0x6800 +// SD Card SPI interface, Slave 13 +// All regs are 8 bits wide, but are accessed as if they are 32 bits +/////////////////////////////////////////////////// +#ifdef USRP2 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 + 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 atr_regs ((atr_regs_t *) ATR_BASE) +#define sdspi_regs ((sdspi_regs_t *) SDSPI_BASE) -/////////////////////////////////////////////////// -// UNUSED, Slave 12 +#endif //USRP2 /////////////////////////////////////////////////// // ICAP, Slave 13 +/////////////////////////////////////////////////// +#ifdef USRP2P -#define ICAP_BASE 0x6A00 typedef struct { uint32_t icap; //only the lower 8 bits matter } icap_regs_t; @@ -564,8 +443,8 @@ typedef struct { // 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 0x6B00 typedef struct { volatile uint32_t txrx0; volatile uint32_t txrx1; @@ -578,13 +457,6 @@ typedef struct { #define spif_regs ((spif_regs_t *) SPIF_BASE) -//////////////////////////////////////////////////////////////// -// Main RAM, Slave 15 - -#define RAM_BASE 0x8000 - - - -/////////////////////////////////////////////////// -#endif +#endif //USRP2P +#endif /* INCLUDED_MEMORY_MAP_H */ diff --git a/firmware/zpu/lib/net_common.c b/firmware/zpu/lib/net_common.c index f70f279ac..2e3257b35 100644 --- a/firmware/zpu/lib/net_common.c +++ b/firmware/zpu/lib/net_common.c @@ -36,17 +36,35 @@ #include <string.h> #include "pkt_ctrl.h" +/*********************************************************************** + * Constants + Globals + **********************************************************************/ static const bool debug = false; - static const size_t out_buff_size = 2048; - static const eth_mac_addr_t BCAST_MAC_ADDR = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; +#define MAX_UDP_LISTENERS 6 //used in the top level application... uint16_t dsp0_dst_port, err0_dst_port, dsp1_dst_port; -// ------------------------------------------------------------------------ +/*********************************************************************** + * 16-bit one's complement sum + **********************************************************************/ +static uint32_t chksum_buffer( + uint16_t *buf, size_t nshorts, + uint32_t initial_chksum +){ + uint32_t chksum = initial_chksum; + for (size_t i = 0; i < nshorts; i++) chksum += buf[i]; + + while (chksum >> 16) chksum = (chksum & 0xffff) + (chksum >> 16); + + return chksum; +} +/*********************************************************************** + * Listener registry + **********************************************************************/ static eth_mac_addr_t _local_mac_addr; static struct ip_addr _local_ip_addr; void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_addr){ @@ -54,10 +72,6 @@ void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_add _local_ip_addr = *ip_addr; } -//------------------------------------------------------------------------- - -#define MAX_UDP_LISTENERS 6 - struct listener_entry { unsigned short port; udp_receiver_t rcvr; @@ -104,9 +118,55 @@ register_udp_listener(int port, udp_receiver_t rcvr) } } -// ------------------------------------------------------------------------ - +/*********************************************************************** + * Protocol framer + **********************************************************************/ +void setup_framer( + eth_mac_addr_t eth_dst, + eth_mac_addr_t eth_src, + struct socket_address sock_dst, + struct socket_address sock_src, + size_t which +){ + struct { + padded_eth_hdr_t eth; + struct ip_hdr ip; + struct udp_hdr udp; + } frame; + + //-- load Ethernet header --// + frame.eth.dst = eth_dst; + frame.eth.src = eth_src; + frame.eth.ethertype = ETHERTYPE_IPV4; + + //-- load IPv4 header --// + IPH_VHLTOS_SET(&frame.ip, 4, 5, 0); + IPH_LEN_SET(&frame.ip, 0); + IPH_ID_SET(&frame.ip, 0); + IPH_OFFSET_SET(&frame.ip, IP_DF); // don't fragment + IPH_TTL_SET(&frame.ip, 32); + IPH_PROTO_SET(&frame.ip, IP_PROTO_UDP); + IPH_CHKSUM_SET(&frame.ip, 0); + frame.ip.src = sock_src.addr; + frame.ip.dest = sock_dst.addr; + IPH_CHKSUM_SET(&frame.ip, chksum_buffer( + (unsigned short *) &frame.ip, + sizeof(frame.ip)/sizeof(short), 0 + )); + + //-- load UDP header --// + frame.udp.src = sock_src.port; + frame.udp.dest = sock_dst.port; + frame.udp.len = 0; + frame.udp.chksum = 0; + + //copy into the framer table registers + memcpy_wa((void *)(sr_proto_framer_regs->table[which].entry + 1), &frame, sizeof(frame)); +} +/*********************************************************************** + * Slow-path packet framing and transmission + **********************************************************************/ /*! * low level routine to assembly an ethernet frame and send it. * @@ -164,43 +224,25 @@ send_pkt( if (debug) printf("sent %d bytes\n", (int)total_len); } -unsigned int CHKSUM(unsigned int x, unsigned int *chksum) -{ - *chksum += x; - *chksum = (*chksum & 0xffff) + (*chksum>>16); - *chksum = (*chksum & 0xffff) + (*chksum>>16); - return x; -} - -static unsigned int -chksum_buffer(unsigned short *buf, int nshorts, unsigned int initial_chksum) -{ - unsigned int chksum = initial_chksum; - for (int i = 0; i < nshorts; i++) - CHKSUM(buf[i], &chksum); - - return chksum; -} - void send_ip_pkt(struct ip_addr dst, int protocol, const void *buf0, size_t len0, const void *buf1, size_t len1) { - int ttl = 32; - struct ip_hdr ip; IPH_VHLTOS_SET(&ip, 4, 5, 0); IPH_LEN_SET(&ip, IP_HLEN + len0 + len1); IPH_ID_SET(&ip, 0); IPH_OFFSET_SET(&ip, IP_DF); /* don't fragment */ - ip._ttl_proto = (ttl << 8) | (protocol & 0xff); - ip._chksum = 0; + IPH_TTL_SET(&ip, 32); + IPH_PROTO_SET(&ip, protocol); + IPH_CHKSUM_SET(&ip, 0); ip.src = _local_ip_addr; ip.dest = dst; - ip._chksum = ~chksum_buffer((unsigned short *) &ip, - sizeof(ip)/sizeof(short), 0); + IPH_CHKSUM_SET(&ip, ~chksum_buffer( + (unsigned short *) &ip, sizeof(ip)/sizeof(short), 0 + )); eth_mac_addr_t dst_mac; bool found = arp_cache_lookup_mac(&ip.dest, &dst_mac); diff --git a/firmware/zpu/lib/net_common.h b/firmware/zpu/lib/net_common.h index 409022352..3cbc5c514 100644 --- a/firmware/zpu/lib/net_common.h +++ b/firmware/zpu/lib/net_common.h @@ -1,6 +1,5 @@ -/* -*- c++ -*- */ /* - * Copyright 2009,2010 Ettus Research LLC + * Copyright 2009-2011 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 @@ -23,12 +22,22 @@ #include <net/socket_address.h> #include <net/eth_mac_addr.h> -/* - * 1's complement sum for IP and UDP headers +/*! + * Setup an entry in the protocol framer for a UDP socket. * - * init chksum to zero to start. + * \param eth_dst ethernet destination mac addr + * \param eth_src ethernet source mac addr + * \param sock_dst udp/ip socket destination + * \param sock_src udp/ip socket source + * \param which the index into the table */ -unsigned int CHKSUM(unsigned int x, unsigned int *chksum); +void setup_framer( + eth_mac_addr_t eth_dst, + eth_mac_addr_t eth_src, + struct socket_address sock_dst, + struct socket_address sock_src, + size_t which +); typedef void (*udp_receiver_t)(struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len); diff --git a/firmware/zpu/lib/u2_init.c b/firmware/zpu/lib/u2_init.c index db26be538..71bd2c594 100644 --- a/firmware/zpu/lib/u2_init.c +++ b/firmware/zpu/lib/u2_init.c @@ -26,9 +26,6 @@ #include "clocks.h" #include "usrp2/fw_common.h" #include "nonstdio.h" -#ifdef USRP2P -#include "u2p_init.h" -#endif /* * We ought to arrange for this to be called before main, but for now, @@ -53,10 +50,6 @@ u2_init(void) i2c_init(); hal_enable_ints(); -#ifdef USRP2P - u2p_init(); -#endif - // flash all leds to let us know board is alive hal_set_led_src(0x0, 0x1f); /* software ctrl */ hal_set_leds(0x0, 0x1f); mdelay(300); diff --git a/firmware/zpu/usrp2/CMakeLists.txt b/firmware/zpu/usrp2/CMakeLists.txt index e54499084..190ea9af1 100644 --- a/firmware/zpu/usrp2/CMakeLists.txt +++ b/firmware/zpu/usrp2/CMakeLists.txt @@ -19,6 +19,8 @@ INCLUDE(${CMAKE_SOURCE_DIR}/lib/CMakeLists.txt) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +ADD_DEFINITIONS(-DUSRP2) + ADD_LIBRARY(libusrp2fw STATIC ${COMMON_SRCS} sd.c @@ -32,6 +34,3 @@ ADD_EXECUTABLE(usrp2_txrx_uhd.elf ${CMAKE_SOURCE_DIR}/apps/txrx_uhd.c) TARGET_LINK_LIBRARIES(usrp2_txrx_uhd.elf libusrp2fw) GEN_OUTPUTS(usrp2_txrx_uhd.elf) -ADD_EXECUTABLE(usrp2_blinkenlights.elf ${CMAKE_SOURCE_DIR}/apps/blinkenlights.c) -TARGET_LINK_LIBRARIES(usrp2_blinkenlights.elf libusrp2fw) -GEN_OUTPUTS(usrp2_blinkenlights.elf) diff --git a/firmware/zpu/usrp2/ethernet.c b/firmware/zpu/usrp2/ethernet.c index 5d4654bda..9a41eb280 100644 --- a/firmware/zpu/usrp2/ethernet.c +++ b/firmware/zpu/usrp2/ethernet.c @@ -1,4 +1,5 @@ /* + * Copyright 2011 Ettus Research LLC * Copyright 2007 Free Software Foundation, Inc. * * This program is free software: you can redistribute it and/or modify @@ -18,7 +19,6 @@ #include "ethernet.h" #include "eth_phy.h" #include "eth_mac.h" -#include "eth_mac_regs.h" #include "pic.h" #include "hal_io.h" #include "nonstdio.h" diff --git a/firmware/zpu/usrp2/memory_map.h b/firmware/zpu/usrp2/memory_map.h deleted file mode 100644 index 79b11759a..000000000 --- a/firmware/zpu/usrp2/memory_map.h +++ /dev/null @@ -1,578 +0,0 @@ -// Copyright 2010-2011 Ettus Research LLC -/* - * 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 <http://www.gnu.org/licenses/>. - */ - -/* Overall Memory Map - * 0000-7FFF 32K RAM space (16K on 1500, 24K on 2000, 32K on DSP) - * 8000-BFFF 16K Packet Router - * C000-FFFF 16K Peripherals - */ - - -#ifndef INCLUDED_MEMORY_MAP_H -#define INCLUDED_MEMORY_MAP_H - -#include <stdint.h> - - -#define MASTER_CLK_RATE 100000000 // 100 MHz - - -//////////////////////////////////////////////////////////////// -// -// Memory map for embedded wishbone bus -// -//////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////// -// Main RAM, Slave 0 - -#define RAM_BASE 0x0000 - -//////////////////////////////////////////////////////////////// -// Packet Router RAM, Slave 1 -// -// The buffers themselves are located in Slave 1, Packet Router RAM. -// The status registers are in Slave 5, Packet Router Status. -// The control register is in Slave 7, Settings Bus. - -#define ROUTER_RAM_BASE 0x8000 - -///////////////////////////////////////////////////// -// 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) - -/////////////////////////////////////////////////// -// Packet Router Status, Slave 5 -// -// The buffers themselves are located in Slave 1, Packet Router RAM. -// The status registers are in Slave 5, Packet Router Status. -// The control register is in Slave 7, Settings Bus. - -#define ROUTER_STATUS_BASE 0xCC00 - -typedef struct { - volatile uint32_t _padding[8]; - volatile uint32_t status; - volatile uint32_t hw_config; // see below - volatile uint32_t time64_secs_rb; - volatile uint32_t time64_ticks_rb; - volatile uint32_t compat_num; - volatile uint32_t irqs; -} router_status_t; - -#define router_status ((router_status_t *) ROUTER_STATUS_BASE) - -// 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 router_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 router_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 ROUTER_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_ROUTER_CTRL 64 -#define SR_UDP_SM 96 -#define SR_TX_DSP 208 -#define SR_TX_CTRL 224 -#define SR_RX_DSP0 160 -#define SR_RX_DSP1 240 -#define SR_RX_CTRL0 176 -#define SR_RX_CTRL1 32 -#define SR_TIME64 192 -#define SR_SIMTIMER 198 -#define SR_LAST 255 - -#define _SR_ADDR(sr) (MISC_OUTPUT_BASE + (sr) * sizeof(uint32_t)) - -// --- packet router control regs --- - -typedef struct { - volatile uint32_t mode_ctrl; - volatile uint32_t ip_addr; - volatile uint32_t data_ports; //dsp0 (low 16) dsp1 (high 16) - volatile uint32_t iface_ctrl; -} router_ctrl_t; - -#define router_ctrl ((router_ctrl_t *) ROUTER_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 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 -#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[1]; - volatile uint32_t dsp0_port; - volatile uint32_t err0_port; - volatile uint32_t dsp1_port; - volatile uint32_t err1_port; -} sr_udp_sm_t; - -// control bits (all expect UDP_SM_LAST_WORD are mutually exclusive) - -// Insert a UDP source port from the table -#define UDP_SM_INS_UDP_SRC_PORT (1 << 21) - -// Insert a UDP dest port from the table -#define UDP_SM_INS_UDP_DST_PORT (1 << 20) - -// 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)) - -// --- VITA TX CTRL regs --- - -typedef struct { - volatile uint32_t num_chan; - volatile uint32_t clear_state; // clears out state machine, fifos, - volatile uint32_t report_sid; - volatile uint32_t policy; - volatile uint32_t cyc_per_up; - volatile uint32_t packets_per_up; -} sr_tx_ctrl_t; - -#define sr_tx_ctrl ((sr_tx_ctrl_t *) _SR_ADDR(SR_TX_CTRL)) - -// --- 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; -} sr_rx_ctrl_t; - -#define sr_rx_ctrl0 ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL0)) -#define sr_rx_ctrl1 ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL1)) - -// ---------------------------------------------------------------- -// VITA49 64 bit time (write only) - /*! - * \brief Time 64 flags - * - * <pre> - * - * 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) - * - * </pre> - */ -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/zpu/usrp2p/CMakeLists.txt b/firmware/zpu/usrp2p/CMakeLists.txt index c7ab9abdb..976dccb9a 100644 --- a/firmware/zpu/usrp2p/CMakeLists.txt +++ b/firmware/zpu/usrp2p/CMakeLists.txt @@ -42,10 +42,3 @@ ADD_EXECUTABLE(usrp2p_txrx_uhd.elf ${CMAKE_SOURCE_DIR}/apps/txrx_uhd.c) TARGET_LINK_LIBRARIES(usrp2p_txrx_uhd.elf libusrp2pfw) GEN_OUTPUTS(usrp2p_txrx_uhd.elf) -ADD_EXECUTABLE(usrp2p_blinkenlights.elf ${CMAKE_SOURCE_DIR}/apps/blinkenlights.c) -TARGET_LINK_LIBRARIES(usrp2p_blinkenlights.elf libusrp2pfw) -GEN_OUTPUTS(usrp2p_blinkenlights.elf) - -ADD_EXECUTABLE(usrp2p_uart_flash_loader.elf ${CMAKE_SOURCE_DIR}/apps/uart_flash_loader.c) -TARGET_LINK_LIBRARIES(usrp2p_uart_flash_loader.elf libusrp2pfw) -GEN_OUTPUTS(usrp2p_uart_flash_loader.elf) diff --git a/firmware/zpu/usrp2p/bootloader/CMakeLists.txt b/firmware/zpu/usrp2p/bootloader/CMakeLists.txt index 2c7efb43a..07f234302 100644 --- a/firmware/zpu/usrp2p/bootloader/CMakeLists.txt +++ b/firmware/zpu/usrp2p/bootloader/CMakeLists.txt @@ -33,8 +33,10 @@ MACRO(GEN_RMI target) ENDMACRO(GEN_RMI) ######################################################################## -ADD_EXECUTABLE(init_bootloader.elf init_bootloader.c) -TARGET_LINK_LIBRARIES(init_bootloader.elf libusrp2pfw) -SET(GEN_OUTPUTS_BIN_SIZE 0x1fff) -GEN_OUTPUTS(init_bootloader.elf) -GEN_RMI(init_bootloader.bin) +ADD_EXECUTABLE(bootloader.elf ${CMAKE_SOURCE_DIR}/apps/txrx_uhd.c) +ADD_DEFINITIONS(-DUSRP2P) +ADD_DEFINITIONS(-DBOOTLOADER) +TARGET_LINK_LIBRARIES(bootloader.elf libusrp2pfw) +SET(GEN_OUTPUTS_BIN_SIZE 0x3fff) +GEN_OUTPUTS(bootloader.elf) +GEN_RMI(bootloader.bin) diff --git a/firmware/zpu/usrp2p/bootloader/fpga_bootloader.c b/firmware/zpu/usrp2p/bootloader/fpga_bootloader.c deleted file mode 100644 index f5a71a8bb..000000000 --- a/firmware/zpu/usrp2p/bootloader/fpga_bootloader.c +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- c -*- */ -/* - * Copyright 2009-2011 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 <http://www.gnu.org/licenses/>. - */ - -/* - * 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 <stdlib.h> -#include <hal_io.h> -#include <nonstdio.h> -#include <mdelay.h> -#include <quadradio/flashdir.h> -#include <xilinx_v5_icap.h> -#include <bootconfig.h> -#include <bootconfig_private.h> -#include <spi_flash.h> -#include <string.h> -#include <bootloader_utils.h> -#include <hal_interrupts.h> - -#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/zpu/usrp2p/bootloader/fw_bootloader.c b/firmware/zpu/usrp2p/bootloader/fw_bootloader.c deleted file mode 100644 index de561cf22..000000000 --- a/firmware/zpu/usrp2p/bootloader/fw_bootloader.c +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- c -*- */ -/* - * Copyright 2009-2011 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 <http://www.gnu.org/licenses/>. - */ - -#include <memory_map.h> -#include <nonstdio.h> -#include <stdlib.h> -#include <bootconfig.h> -#include <bootconfig_private.h> -#include <bootloader_utils.h> -#include <hal_interrupts.h> - - -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/zpu/usrp2p/bootloader/icap_test.c b/firmware/zpu/usrp2p/bootloader/icap_test.c deleted file mode 100644 index 5feb9d014..000000000 --- a/firmware/zpu/usrp2p/bootloader/icap_test.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010 Ettus Research LLC - * - */ - -#include <memory_map.h> -#include <hal_io.h> -#include <xilinx_s3_icap.h> -#include <nonstdio.h> - -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/zpu/usrp2p/bootloader/init_bootloader.c b/firmware/zpu/usrp2p/bootloader/init_bootloader.c index 66481eb25..d797edce4 100644 --- a/firmware/zpu/usrp2p/bootloader/init_bootloader.c +++ b/firmware/zpu/usrp2p/bootloader/init_bootloader.c @@ -1,8 +1,19 @@ -/* -*- c++ -*- */ -/* - * Copyright 2010-2011 Ettus Research LLC - * - */ +// +// Copyright 2010-2011 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 <http://www.gnu.org/licenses/>. +// #include <memory_map.h> #include <nonstdio.h> @@ -10,7 +21,6 @@ #include <xilinx_s3_icap.h> #include <spi_flash.h> #include <spi_flash_private.h> -//#include <clocks.h> #include <mdelay.h> #include <ihex.h> #include <bootloader_utils.h> @@ -19,12 +29,7 @@ #include <i2c.h> #include "usrp2/fw_common.h" -//void pic_interrupt_handler() __attribute__ ((interrupt_handler)); - -void pic_interrupt_handler() -{ - // nop stub -} +#define BUTTON_PUSHED ((router_status->irqs & PIC_BUTTON) ? 0 : 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 diff --git a/firmware/zpu/usrp2p/bootloader/serial_loader_burner.c b/firmware/zpu/usrp2p/bootloader/serial_loader_burner.c deleted file mode 100644 index 6d5d135ab..000000000 --- a/firmware/zpu/usrp2p/bootloader/serial_loader_burner.c +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009-2011 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 <http://www.gnu.org/licenses/>. - */ - -#include <hal_io.h> -#include <nonstdio.h> -#include <mdelay.h> -#include <gdbstub2.h> - -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/zpu/usrp2p/bootloader/udp_bootloader.c b/firmware/zpu/usrp2p/bootloader/udp_bootloader.c new file mode 100644 index 000000000..118de2ae9 --- /dev/null +++ b/firmware/zpu/usrp2p/bootloader/udp_bootloader.c @@ -0,0 +1,200 @@ +// +// Copyright 2010-2011 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 <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <lwip/ip.h> +#include <lwip/udp.h> +#include "u2_init.h" +#include "memory_map.h" +#include "spi.h" +#include "hal_io.h" +#include "pic.h" +#include <stdbool.h> +#include "ethernet.h" +#include "nonstdio.h" +#include <net/padded_eth_hdr.h> +#include <net_common.h> +#include "memcpy_wa.h" +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include "clocks.h" +#include "usrp2/fw_common.h" +#include <i2c.h> +#include <ethertype.h> +#include <arp_cache.h> +#include "udp_fw_update.h" +#include "pkt_ctrl.h" +#include "banal.h" +#include <bootloader_utils.h> +#include <spi_flash.h> +#include <xilinx_s3_icap.h> +#include <mdelay.h> + +#define BUTTON_PUSHED ((router_status->irqs & PIC_BUTTON) ? 0 : 1) + +static void handle_inp_packet(uint32_t *buff, size_t num_lines){ + + //test if its an ip recovery packet + typedef struct{ + padded_eth_hdr_t eth_hdr; + char code[4]; + union { + struct ip_addr ip_addr; + } data; + }recovery_packet_t; + recovery_packet_t *recovery_packet = (recovery_packet_t *)buff; + if (recovery_packet->eth_hdr.ethertype == 0xbeee && strncmp(recovery_packet->code, "addr", 4) == 0){ + printf("Got ip recovery packet: "); print_ip_addr(&recovery_packet->data.ip_addr); newline(); + set_ip_addr(&recovery_packet->data.ip_addr); + return; + } + + //pass it to the slow-path handler + handle_eth_packet(buff, num_lines); +} + + +//------------------------------------------------------------------ + +/* + * Called when eth phy state changes (w/ interrupts disabled) + */ +void link_changed_callback(int speed){ + printf("\neth link changed: speed = %d\n", speed); + if (speed != 0){ + hal_set_leds(LED_RJ45, LED_RJ45); + pkt_ctrl_set_routing_mode(PKT_CTRL_ROUTING_MODE_MASTER); + send_gratuitous_arp(); + } + else{ + hal_set_leds(0x0, LED_RJ45); + pkt_ctrl_set_routing_mode(PKT_CTRL_ROUTING_MODE_SLAVE); + } +} + +static void do_the_bootload_thing(void) { + + bool production_image = find_safe_booted_flag(); + set_safe_booted_flag(0); //haven't booted yet + + if(BUTTON_PUSHED) { //see memory_map.h + puts("Starting USRP2+ in safe mode. I am a brick. Feel free to reprogram me via the UDP burner."); + return; + //no longer necessary since we can just burn from UDP via the bootloader now +/* + if(is_valid_fw_image(SAFE_FW_IMAGE_LOCATION_ADDR)) { + set_safe_booted_flag(1); //let the firmware know it's the safe image + spi_flash_read(SAFE_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE); + start_program(); + 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 reprogram me via the UDP burner."); + return; + } +*/ + } + + 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); + mdelay(300); //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..."); + } + 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); + puts("Finished loading. Starting image."); + mdelay(300); + start_program(); + 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. + mdelay(300); + icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + return; + } + 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); + puts("Finished loading. Starting image."); + mdelay(300); + start_program(); + puts("ERROR: return from main program! This should never happen!"); + mdelay(300); + icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + return; + } + puts("ERROR: no safe firmware image available. I am a brick. Feel free to reprogram me via the UDP burner."); +} + +int +main(void) +{ + u2_init(); + spif_init(); + + set_default_mac_addr(); + set_default_ip_addr(); + + putstr("\nN210 bootloader, UDP edition\n"); + print_mac_addr(ethernet_mac_addr()); newline(); + print_ip_addr(get_ip_addr()); newline(); + printf("FPGA compatibility number: %d\n", USRP2_FPGA_COMPAT_NUM); + printf("Firmware compatibility number: %d\n", USRP2_FW_COMPAT_NUM); + + do_the_bootload_thing(); + + //if we reach this point, the bootloader has fallen through, so we initalize the UDP handler for updating + + //1) register the addresses into the network stack + //TODO: make this a fixed IP address, don't depend on EEPROM + register_addrs(ethernet_mac_addr(), get_ip_addr()); + pkt_ctrl_program_inspector(get_ip_addr(), USRP2_UDP_DSP0_PORT); + + //2) register callbacks for udp ports we service + init_udp_listeners(); + register_udp_listener(USRP2_UDP_UPDATE_PORT, handle_udp_fw_update_packet); + + pkt_ctrl_set_routing_mode(PKT_CTRL_ROUTING_MODE_SLAVE); + + //4) setup ethernet hardware to bring the link up + ethernet_register_link_changed_callback(link_changed_callback); + ethernet_init(); + + while(true){ + + size_t num_lines; + void *buff = pkt_ctrl_claim_incoming_buffer(&num_lines); + if (buff != NULL){ + handle_inp_packet((uint32_t *)buff, num_lines); + pkt_ctrl_release_incoming_buffer(); + } + + pic_interrupt_handler(); + } +} diff --git a/firmware/zpu/usrp2p/bootloader_utils.c b/firmware/zpu/usrp2p/bootloader_utils.c index 371c518a7..1efa643b6 100644 --- a/firmware/zpu/usrp2p/bootloader_utils.c +++ b/firmware/zpu/usrp2p/bootloader_utils.c @@ -10,8 +10,14 @@ #include <string.h> #include <bootloader_utils.h> #include <spi_flash.h> +#include <i2c.h> #include <memory_map.h> #include <nonstdio.h> +#include <xilinx_s3_icap.h> +#include <mdelay.h> +#include "spi.h" + +#define BUTTON_PUSHED ((router_status->irqs & PIC_BUTTON) ? 0 : 1) int is_valid_fpga_image(uint32_t addr) { // printf("is_valid_fpga_image(): starting with addr=%x...\n", addr); @@ -46,3 +52,53 @@ void start_program(void) //all this does is tap that register *((volatile uint32_t *) SR_ADDR_BLDRDONE) = 1; } + +void do_the_bootload_thing(void) { + spif_init(); //initialize SPI flash clock + + bool production_image = find_safe_booted_flag(); + set_safe_booted_flag(0); //haven't booted yet + + if(BUTTON_PUSHED) { //see memory_map.h + puts("Starting USRP2+ in safe mode. Loading safe firmware."); + return; + } + + 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); + mdelay(300); //so serial output can finish + icap_reload_fpga(PROD_FPGA_IMAGE_LOCATION_ADDR); + } + puts("No valid production FPGA image found.\nFalling through to built-in firmware."); + return; + } + 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); + puts("Finished loading. Starting image."); + mdelay(300); + start_program(); + 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. + mdelay(300); + icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + return; + } + puts("No valid production firmware found. Falling through to built-in 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); + puts("Finished loading. Starting image."); + mdelay(300); + start_program(); + puts("ERROR: return from main program! This should never happen!"); + mdelay(300); + icap_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR); + return; + } + puts("ERROR: no safe firmware image available. Falling through to built-in firmware."); + */ +} diff --git a/firmware/zpu/usrp2p/bootloader_utils.h b/firmware/zpu/usrp2p/bootloader_utils.h index 0f49ae6cd..d70299b88 100644 --- a/firmware/zpu/usrp2p/bootloader_utils.h +++ b/firmware/zpu/usrp2p/bootloader_utils.h @@ -20,3 +20,4 @@ int is_valid_fpga_image(uint32_t addr); int is_valid_fw_image(uint32_t addr); void start_program(void); +void do_the_bootload_thing(void); diff --git a/firmware/zpu/usrp2p/ethernet.c b/firmware/zpu/usrp2p/ethernet.c index 03891f959..f5bd9f121 100644 --- a/firmware/zpu/usrp2p/ethernet.c +++ b/firmware/zpu/usrp2p/ethernet.c @@ -1,4 +1,5 @@ /* + * Copyright 2011 Ettus Research LLC * Copyright 2007 Free Software Foundation, Inc. * * This program is free software: you can redistribute it and/or modify @@ -21,7 +22,6 @@ #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> |