diff options
Diffstat (limited to 'firmware/zpu/usrp2p/bootloader')
-rw-r--r-- | firmware/zpu/usrp2p/bootloader/CMakeLists.txt | 12 | ||||
-rw-r--r-- | firmware/zpu/usrp2p/bootloader/fpga_bootloader.c | 202 | ||||
-rw-r--r-- | firmware/zpu/usrp2p/bootloader/fw_bootloader.c | 50 | ||||
-rw-r--r-- | firmware/zpu/usrp2p/bootloader/icap_test.c | 31 | ||||
-rw-r--r-- | firmware/zpu/usrp2p/bootloader/init_bootloader.c | 29 | ||||
-rw-r--r-- | firmware/zpu/usrp2p/bootloader/serial_loader_burner.c | 49 | ||||
-rw-r--r-- | firmware/zpu/usrp2p/bootloader/udp_bootloader.c | 200 |
7 files changed, 224 insertions, 349 deletions
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(); + } +} |