diff options
38 files changed, 457 insertions, 1808 deletions
diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index 9c1873e1c..e9c98c26e 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -28,12 +28,10 @@ #include "memory_map.h" #include "spi.h" #include "hal_io.h" -#include "buffer_pool.h" #include "pic.h" #include <stdbool.h> #include "ethernet.h" #include "nonstdio.h" -#include "dbsm.h" #include <net/padded_eth_hdr.h> #include <net_common.h> #include "memcpy_wa.h" @@ -42,87 +40,12 @@ #include <string.h> #include "clocks.h" #include "usrp2/fw_common.h" -#include <i2c_async.h> #include <i2c.h> #include <ethertype.h> #include <arp_cache.h> #include "udp_fw_update.h" - -/* - * Full duplex Tx and Rx between ethernet and DSP pipelines - * - * Buffer 1 is used by the cpu to send frames to the host. - * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow - * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow - */ -//#define CPU_RX_BUF 0 // eth -> cpu - -#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer) -#define DSP_RX_BUF_1 3 // dsp rx -> eth -#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer) -#define DSP_TX_BUF_1 5 // eth -> dsp tx - -/* - * ================================================================ - * configure DSP TX double buffering state machine (eth -> dsp) - * ================================================================ - */ - -// DSP Tx reads ethernet header words -#define DSP_TX_FIRST_LINE ((sizeof(padded_eth_hdr_t) + sizeof(struct ip_hdr) + sizeof(struct udp_hdr))/sizeof(uint32_t)) - -// Receive from ethernet -buf_cmd_args_t dsp_tx_recv_args = { - PORT_ETH, - 0, - BP_LAST_LINE -}; - -// send to DSP Tx -buf_cmd_args_t dsp_tx_send_args = { - PORT_DSP, - DSP_TX_FIRST_LINE, // starts just past transport header - 0 // filled in from last_line register -}; - -dbsm_t dsp_tx_sm; // the state machine - -/* - * ================================================================ - * configure DSP RX double buffering state machine (dsp -> eth) - * ================================================================ - */ - -static const uint32_t rx_ctrl_word = 1 << 16; - -// DSP Rx writes ethernet header words -#define DSP_RX_FIRST_LINE sizeof(rx_ctrl_word)/sizeof(uint32_t) - -static bool dbsm_rx_inspector(dbsm_t *sm, int buf_this){ - size_t num_lines = buffer_pool_status->last_line[buf_this]-DSP_RX_FIRST_LINE; - ((uint32_t*)buffer_ram(buf_this))[0] = (num_lines*sizeof(uint32_t)) | (1 << 16); - return false; -} - -// receive from DSP -buf_cmd_args_t dsp_rx_recv_args = { - PORT_DSP, - DSP_RX_FIRST_LINE, - BP_LAST_LINE -}; - -// send to ETH -buf_cmd_args_t dsp_rx_send_args = { - PORT_ETH, - 0, // starts with ethernet header in line 0 - 0, // filled in from list_line register -}; - -dbsm_t dsp_rx_sm; // the state machine - - -// The mac address of the host we're sending to. -eth_mac_addr_t host_mac_addr; +#include "pkt_ctrl.h" +#include "banal.h" static void setup_network(void); @@ -130,16 +53,7 @@ static void setup_network(void); // the fast-path setup global variables // ---------------------------------------------------------------- static eth_mac_addr_t fp_mac_addr_src, fp_mac_addr_dst; -static struct socket_address fp_socket_src, fp_socket_dst; - -// ---------------------------------------------------------------- -void start_rx_streaming_cmd(void); -void stop_rx_cmd(void); - -static void print_ip_addr(const void *t){ - uint8_t *p = (uint8_t *)t; - printf("%d.%d.%d.%d", p[0], p[1], p[2], p[3]); -} +extern struct socket_address fp_socket_src, fp_socket_dst; void handle_udp_data_packet( struct socket_address src, struct socket_address dst, @@ -166,41 +80,11 @@ void handle_udp_data_packet( //setup network and vrt setup_network(); - // kick off the state machine - dbsm_start(&dsp_rx_sm); - } #define OTW_GPIO_BANK_TO_NUM(bank) \ (((bank) == USRP2_DIR_RX)? (GPIO_RX_BANK) : (GPIO_TX_BANK)) -//setup the output data -static usrp2_ctrl_data_t ctrl_data_out; -static struct socket_address i2c_src; -static struct socket_address spi_src; - -static volatile bool i2c_done = false; -void i2c_read_done_callback(void) { - //printf("I2C read done callback\n"); - i2c_async_data_ready(ctrl_data_out.data.i2c_args.data); - i2c_done = true; - i2c_register_callback(0); -} - -void i2c_write_done_callback(void) { - //printf("I2C write done callback\n"); - i2c_done = true; - i2c_register_callback(0); -} - -static volatile bool spi_done = false; -static volatile uint32_t spi_readback_data; -void get_spi_readback_data(void) { - ctrl_data_out.data.spi_args.data = spi_get_data(); - spi_done = true; - spi_register_callback(0); -} - void handle_udp_ctrl_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len @@ -226,6 +110,7 @@ void handle_udp_ctrl_packet( } //setup the output data + usrp2_ctrl_data_t ctrl_data_out; ctrl_data_out.proto_ver = USRP2_FW_COMPAT_NUM; ctrl_data_out.id=USRP2_CTRL_ID_HUH_WHAT; ctrl_data_out.seq=ctrl_data_in->seq; @@ -239,7 +124,6 @@ void handle_udp_ctrl_packet( case USRP2_CTRL_ID_WAZZUP_BRO: ctrl_data_out.id = USRP2_CTRL_ID_WAZZUP_DUDE; memcpy(&ctrl_data_out.data.ip_addr, get_ip_addr(), sizeof(struct ip_addr)); - send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); break; /******************************************************************* @@ -247,21 +131,19 @@ void handle_udp_ctrl_packet( ******************************************************************/ case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:{ //transact - bool success = spi_async_transact( - //(ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX, + uint32_t result = spi_transact( + (ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX, ctrl_data_in->data.spi_args.dev, //which device ctrl_data_in->data.spi_args.data, //32 bit data ctrl_data_in->data.spi_args.num_bits, //length in bits - (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | //flags - (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL, - get_spi_readback_data //callback + (ctrl_data_in->data.spi_args.mosi_edge == USRP2_CLK_EDGE_RISE)? SPIF_PUSH_FALL : SPIF_PUSH_RISE | + (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL ); //load output + ctrl_data_out.data.spi_args.data = result; ctrl_data_out.id = USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE; - spi_src = src; } -// send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); break; /******************************************************************* @@ -269,13 +151,11 @@ void handle_udp_ctrl_packet( ******************************************************************/ case USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO:{ uint8_t num_bytes = ctrl_data_in->data.i2c_args.bytes; - i2c_register_callback(i2c_read_done_callback); - i2c_async_read( + i2c_read( ctrl_data_in->data.i2c_args.addr, + ctrl_data_out.data.i2c_args.data, num_bytes ); - i2c_src = src; -// i2c_dst = dst; ctrl_data_out.id = USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE; ctrl_data_out.data.i2c_args.bytes = num_bytes; } @@ -283,14 +163,11 @@ void handle_udp_ctrl_packet( case USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO:{ uint8_t num_bytes = ctrl_data_in->data.i2c_args.bytes; - i2c_register_callback(i2c_read_done_callback); - i2c_async_write( + i2c_write( ctrl_data_in->data.i2c_args.addr, ctrl_data_in->data.i2c_args.data, num_bytes ); - i2c_src = src; -// i2c_dst = dst; ctrl_data_out.id = USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE; ctrl_data_out.data.i2c_args.bytes = num_bytes; } @@ -322,7 +199,6 @@ void handle_udp_ctrl_packet( } ctrl_data_out.id = USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE; - send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); break; case USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO: @@ -345,7 +221,6 @@ void handle_udp_ctrl_packet( } ctrl_data_out.id = USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE; - send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); break; case USRP2_CTRL_ID_SO_LIKE_CAN_YOU_READ_THIS_UART_BRO:{ @@ -372,32 +247,11 @@ void handle_udp_ctrl_packet( default: ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; - send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); } - + send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); } -/* - * Called when an ethernet packet is received. - * Return true if we handled it here, otherwise - * it'll be passed on to the DSP Tx pipe - */ -static bool -eth_pkt_inspector(dbsm_t *sm, int bufno) -{ - //point me to the ethernet frame - uint32_t *buff = (uint32_t *)buffer_ram(bufno); - - //treat this as fast-path data? - // We have to do this operation as fast as possible. - // Therefore, we do not check all the headers, - // just check that the udp port matches - // and that the vrt header is non zero. - // In the future, a hardware state machine will do this... - if ( //warning! magic numbers approaching.... - (((buff + ((2 + 14 + 20)/sizeof(uint32_t)))[0] & 0xffff) == USRP2_UDP_DATA_PORT) && - ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[1] != USRP2_INVALID_VRT_HEADER) - ) return false; +static void handle_inp_packet(uint32_t *buff, size_t num_lines){ //test if its an ip recovery packet typedef struct{ @@ -411,42 +265,30 @@ eth_pkt_inspector(dbsm_t *sm, int bufno) 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 true; + return; } //pass it to the slow-path handler - size_t len = buffer_pool_status->last_line[bufno] - 3; - handle_eth_packet(buff, len); - return true; + handle_eth_packet(buff, num_lines); } -//------------------------------------------------------------------ -/* - * 1's complement sum for IP and UDP headers - * - * init chksum to zero to start. - */ -static unsigned int -CHKSUM(unsigned int x, unsigned int *chksum) -{ - *chksum += x; - *chksum = (*chksum & 0xffff) + (*chksum>>16); - *chksum = (*chksum & 0xffff) + (*chksum>>16); - return x; -} +//------------------------------------------------------------------ /* * Called when eth phy state changes (w/ interrupts disabled) */ -volatile bool link_is_up = false; // eth handler sets this -void -link_changed_callback(int speed) -{ - link_is_up = speed != 0; - hal_set_leds(link_is_up ? LED_RJ45 : 0x0, LED_RJ45); - printf("\neth link changed: speed = %d\n", speed); - if (link_is_up) send_gratuitous_arp(); +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 setup_network(void){ @@ -483,15 +325,6 @@ static void setup_network(void){ sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum } -inline static void -buffer_irq_handler(unsigned irq) -{ - uint32_t status = buffer_pool_status->status; - - dbsm_process_status(&dsp_tx_sm, status); - dbsm_process_status(&dsp_rx_sm, status); -} - int main(void) { @@ -515,72 +348,40 @@ main(void) printf("Firmware compatibility number: %d\n", USRP2_FW_COMPAT_NUM); //1) register the addresses into the network stack - register_mac_addr(ethernet_mac_addr()); - register_ip_addr(get_ip_addr()); - + register_addrs(ethernet_mac_addr(), get_ip_addr()); + pkt_ctrl_program_inspector(get_ip_addr(), USRP2_UDP_CTRL_PORT, USRP2_UDP_DATA_PORT); + //2) register callbacks for udp ports we service register_udp_listener(USRP2_UDP_CTRL_PORT, handle_udp_ctrl_packet); register_udp_listener(USRP2_UDP_DATA_PORT, handle_udp_data_packet); register_udp_listener(USRP2_UDP_UPDATE_PORT, handle_udp_fw_update_packet); - //3) setup ethernet hardware to bring the link up + //3) set the routing mode to slave and send a garp + pkt_ctrl_set_routing_mode(PKT_CTRL_ROUTING_MODE_SLAVE); + send_gratuitous_arp(); + + //4) setup ethernet hardware to bring the link up ethernet_register_link_changed_callback(link_changed_callback); ethernet_init(); - // initialize double buffering state machine for ethernet -> DSP Tx - - dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0, - &dsp_tx_recv_args, &dsp_tx_send_args, - eth_pkt_inspector); - - - // initialize double buffering state machine for DSP RX -> Ethernet - - dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0, - &dsp_rx_recv_args, &dsp_rx_send_args, - dbsm_rx_inspector); - - sr_tx_ctrl->clear_state = 1; - bp_clear_buf(DSP_TX_BUF_0); - bp_clear_buf(DSP_TX_BUF_1); + while(true){ - // kick off the state machine - dbsm_start(&dsp_tx_sm); - - //int which = 0; - - while(1){ - // hal_gpio_write(GPIO_TX_BANK, which, 0x8000); - // which ^= 0x8000; - - buffer_irq_handler(0); - - if(i2c_done) { - i2c_done = false; - send_udp_pkt(USRP2_UDP_CTRL_PORT, i2c_src, &ctrl_data_out, sizeof(ctrl_data_out)); - //printf("Sending UDP packet from main loop for I2C...\n"); - } - - if(spi_done) { - spi_done = false; - send_udp_pkt(USRP2_UDP_CTRL_PORT, spi_src, &ctrl_data_out, sizeof(ctrl_data_out)); + 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(); } int pending = pic_regs->pending; // poll for under or overrun if (pending & PIC_UNDERRUN_INT){ - //dbsm_handle_tx_underrun(&dsp_tx_sm); pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt putchar('U'); } if (pending & PIC_OVERRUN_INT){ - //dbsm_handle_rx_overrun(&dsp_rx_sm); pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt - - // FIXME Figure out how to handle this robustly. - // Any buffers that are emptying should be allowed to drain... - putchar('O'); } } diff --git a/firmware/microblaze/lib/Makefile.inc b/firmware/microblaze/lib/Makefile.inc index 38c630df4..d99fc4d98 100644 --- a/firmware/microblaze/lib/Makefile.inc +++ b/firmware/microblaze/lib/Makefile.inc @@ -21,10 +21,7 @@ COMMON_SRCS = \ $(top_srcdir)/lib/u2_init.c \ $(top_srcdir)/lib/abort.c \ $(top_srcdir)/lib/ad9510.c \ - $(top_srcdir)/lib/bsm12.c \ - $(top_srcdir)/lib/buffer_pool.c \ $(top_srcdir)/lib/clocks.c \ - $(top_srcdir)/lib/dbsm.c \ $(top_srcdir)/lib/eeprom.c \ $(top_srcdir)/lib/eth_addrs.c \ $(top_srcdir)/lib/eth_mac.c \ @@ -33,13 +30,13 @@ COMMON_SRCS = \ $(top_srcdir)/lib/hal_io.c \ $(top_srcdir)/lib/hal_uart.c \ $(top_srcdir)/lib/i2c.c \ - $(top_srcdir)/lib/i2c_async.c \ $(top_srcdir)/lib/mdelay.c \ $(top_srcdir)/lib/memcpy_wa.c \ $(top_srcdir)/lib/memset_wa.c \ $(top_srcdir)/lib/nonstdio.c \ $(top_srcdir)/lib/pic.c \ - $(top_srcdir)/lib/print_mac_addr.c \ + $(top_srcdir)/lib/pkt_ctrl.c \ + $(top_srcdir)/lib/print_addrs.c \ $(top_srcdir)/lib/print_rmon_regs.c \ $(top_srcdir)/lib/print_buffer.c \ $(top_srcdir)/lib/printf.c \ diff --git a/firmware/microblaze/lib/banal.h b/firmware/microblaze/lib/banal.h index 7b3c71a20..eb7ed509a 100644 --- a/firmware/microblaze/lib/banal.h +++ b/firmware/microblaze/lib/banal.h @@ -19,24 +19,8 @@ #define INCLUDED_BANAL_H #include <stdint.h> -#include <lwip/ip_addr.h> -/* - * 1's complement sum for IP and UDP headers - * - * init chksum to zero to start. - */ -static inline unsigned int -CHKSUM(unsigned int x, unsigned int *chksum) -{ - *chksum += x; - *chksum = (*chksum & 0xffff) + (*chksum>>16); - *chksum = (*chksum & 0xffff) + (*chksum>>16); - return x; -} - -unsigned int -chksum_buffer(unsigned short *buf, int nshorts, unsigned int initial_chksum); +#define dimof(x) (sizeof(x)/sizeof(x[0])) //-------------- unsigned get_int 8, 16, 32, 64 --------------// @@ -84,7 +68,4 @@ get_int64(const unsigned char *s) return get_uint64(s); } -void -print_ip(struct ip_addr ip); - #endif /* INCLUDED_BANAL_H */ diff --git a/firmware/microblaze/lib/bsm12.c b/firmware/microblaze/lib/bsm12.c deleted file mode 100644 index 3f17fe42d..000000000 --- a/firmware/microblaze/lib/bsm12.c +++ /dev/null @@ -1,319 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * buffer state machine: 1 input to two outputs - * - * Typically used to read packets from the ethernet and then after inspecting, - * handle the packet in firmware or pass it on to 1 of the 2 buffer destinations. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "bsm12.h" -#include "memory_map.h" -#include "buffer_pool.h" -#include <stdbool.h> -#include "nonstdio.h" -#include <stdlib.h> - -typedef enum { - BS_EMPTY, - BS_FILLING, - BS_FULL, - BS_EMPTYING, -} buffer_state_t; - -static buffer_state_t buffer_state[NBUFFERS]; -static uint32_t last_send_ctrl[NBUFFERS]; -static int8_t buffer_target[NBUFFERS]; // -1, 0 or 1. -static uint8_t buffer_dst[NBUFFERS]; // 0 or 1. Valid only when BF_EMPTYING - -#define ST_IDLE (-1) - -void -bsm12_init(bsm12_t *sm, int buf0, - const buf_cmd_args_t *recv, - const buf_cmd_args_t *send0, - const buf_cmd_args_t *send1, - bsm12_inspector_t inspect) -{ - if (buf0 & 0x3) // precondition: buf0 % 4 == 0 - abort(); - - sm->buf0 = buf0; - sm->running = false; - sm->recv_args = *recv; - sm->send_args[0] = *send0; - sm->send_args[1] = *send1; - - sm->rx_state = ST_IDLE; - sm->tx_state[0] = ST_IDLE; - sm->tx_state[1] = ST_IDLE; - - sm->inspect = inspect; - - sm->bps_error = BPS_ERROR(buf0 + 0) | BPS_ERROR(buf0 + 1) | BPS_ERROR(buf0 + 2); - sm->bps_done = BPS_DONE(buf0 + 0) | BPS_DONE(buf0 + 1) | BPS_DONE(buf0 + 2); - sm->bps_error_or_done = sm->bps_error | sm->bps_done; - - // How much to adjust the last_line register. - // It's 1 for everything but the ethernet. - sm->last_line_adj = recv->port == PORT_ETH ? 3 : 1; - - buffer_state[sm->buf0 + 0] = BS_EMPTY; - buffer_state[sm->buf0 + 1] = BS_EMPTY; - buffer_state[sm->buf0 + 2] = BS_EMPTY; - - buffer_target[sm->buf0 + 0] = -1; - buffer_target[sm->buf0 + 1] = -1; - buffer_target[sm->buf0 + 2] = -1; - - for (int i = 0; i < NBUFFERS; i++) - sm->next_buf[i] = buf0; - - sm->next_buf[buf0 + 0] = buf0 + 1; - sm->next_buf[buf0 + 1] = buf0 + 2; - sm->next_buf[buf0 + 2] = buf0 + 0; - - for (int i = 0; i < 3; i++){ - sm->precomputed_receive_to_buf_ctrl_word[i] = - (BPC_READ - | BPC_BUFFER(sm->buf0 + i) - | BPC_PORT(sm->recv_args.port) - | BPC_STEP(1) - | BPC_FIRST_LINE(sm->recv_args.first_line) - | BPC_LAST_LINE(sm->recv_args.last_line)); - - for (int j = 0; j < 2; j++){ - sm->precomputed_send_from_buf_ctrl_word[i][j] = - (BPC_WRITE - | BPC_BUFFER(sm->buf0 + i) - | BPC_PORT(sm->send_args[j].port) - | BPC_STEP(1) - | BPC_FIRST_LINE(sm->send_args[j].first_line) - | BPC_LAST_LINE(0)); // last line filled in at runtime - } - } -} - -static inline void -bsm12_receive_to_buf(bsm12_t *sm, int bufno) -{ - buffer_pool_ctrl->ctrl = sm->precomputed_receive_to_buf_ctrl_word[bufno & 0x3]; -} - -static inline void -bsm12_send_from_buf(bsm12_t *sm, int bufno, int dst_idx) -{ - dst_idx &= 0x1; - - uint32_t t = - (sm->precomputed_send_from_buf_ctrl_word[bufno & 0x3][dst_idx] - | BPC_LAST_LINE(buffer_pool_status->last_line[bufno] - sm->last_line_adj)); - - buffer_pool_ctrl->ctrl = t; - last_send_ctrl[bufno] = t; - buffer_dst[bufno] = dst_idx; -} - -static inline void -bsm12_resend_from_buf(bsm12_t *sm, int bufno) -{ - buffer_pool_ctrl->ctrl = last_send_ctrl[bufno]; -} - -void -bsm12_start(bsm12_t *sm) -{ - sm->running = true; - - buffer_state[sm->buf0 + 0] = BS_EMPTY; - buffer_state[sm->buf0 + 1] = BS_EMPTY; - buffer_state[sm->buf0 + 2] = BS_EMPTY; - - buffer_target[sm->buf0 + 0] = -1; - buffer_target[sm->buf0 + 1] = -1; - buffer_target[sm->buf0 + 2] = -1; - - bp_clear_buf(sm->buf0 + 0); - bp_clear_buf(sm->buf0 + 1); - bp_clear_buf(sm->buf0 + 2); - - sm->rx_state = 0; - sm->tx_state[0] = ST_IDLE; - sm->tx_state[1] = ST_IDLE; - bsm12_receive_to_buf(sm, sm->buf0); - buffer_state[sm->buf0] = BS_FILLING; -} - -void -bsm12_stop(bsm12_t *sm) -{ - sm->running = false; - bp_clear_buf(sm->buf0 + 0); - bp_clear_buf(sm->buf0 + 1); - bp_clear_buf(sm->buf0 + 2); - buffer_state[sm->buf0 + 0] = BS_EMPTY; - buffer_state[sm->buf0 + 1] = BS_EMPTY; - buffer_state[sm->buf0 + 2] = BS_EMPTY; -} - -static void bsm12_process_helper(bsm12_t *sm, int buf_this); -static void bsm12_error_helper(bsm12_t *sm, int buf_this); - -void -bsm12_process_status(bsm12_t *sm, uint32_t status) -{ - // anything for us? - if ((status & sm->bps_error_or_done) == 0 || !sm->running) - return; - - if (status & sm->bps_error){ - // Most likely an ethernet Rx error. We just restart the transfer. - if (status & (BPS_ERROR(sm->buf0 + 0))) - bsm12_error_helper(sm, sm->buf0 + 0); - - if (status & (BPS_ERROR(sm->buf0 + 1))) - bsm12_error_helper(sm, sm->buf0 + 1); - - if (status & (BPS_ERROR(sm->buf0 + 2))) - bsm12_error_helper(sm, sm->buf0 + 2); - } - - if (status & BPS_DONE(sm->buf0 + 0)) - bsm12_process_helper(sm, sm->buf0 + 0); - - if (status & BPS_DONE(sm->buf0 + 1)) - bsm12_process_helper(sm, sm->buf0 + 1); - - if (status & BPS_DONE(sm->buf0 + 2)) - bsm12_process_helper(sm, sm->buf0 + 2); -} - -static void -bsm12_process_helper(bsm12_t *sm, int buf_this) -{ - bp_clear_buf(buf_this); - - if (buffer_state[buf_this] == BS_FILLING){ - - buffer_state[buf_this] = BS_FULL; - buffer_target[buf_this] = -1; - - // - // where does this packet go? - // - int dst = sm->inspect(sm, buf_this); - if (dst == -1){ - // - // f/w handled the packet; refill the buffer - // - bsm12_receive_to_buf(sm, buf_this); - buffer_state[buf_this] = BS_FILLING; - buffer_target[buf_this] = -1; - sm->rx_state = buf_this & 0x3; - } - else { // goes to dst 0 or 1 - // - // If the next buffer is empty, start a receive on it - // - int t = sm->next_buf[buf_this]; - if (buffer_state[t] == BS_EMPTY){ - bsm12_receive_to_buf(sm, t); - buffer_state[t] = BS_FILLING; - buffer_target[t] = -1; - sm->rx_state = t & 0x3; - } - else - sm->rx_state = ST_IDLE; - - // - // If the destination is idle, start the xfer, othewise remember it - // - if (sm->tx_state[dst] == ST_IDLE){ - bsm12_send_from_buf(sm, buf_this, dst); - sm->tx_state[dst] = buf_this & 0x3; - buffer_state[buf_this] = BS_EMPTYING; - buffer_target[buf_this] = -1; - } - else { - buffer_target[buf_this] = dst; - } - } - } - - else { // BS_EMPTYING - - buffer_state[buf_this] = BS_EMPTY; - buffer_target[buf_this] = -1; - - if (sm->rx_state == ST_IDLE){ // fire off another receive - sm->rx_state = buf_this & 0x3; - bsm12_receive_to_buf(sm, buf_this); - buffer_state[buf_this] = BS_FILLING; - buffer_target[buf_this] = -1; - } - - int dst = buffer_dst[buf_this]; // the dst we were emptying into - // is the next buffer full and for us? - int t = sm->next_buf[buf_this]; - if (buffer_target[t] == dst){ // yes, - bsm12_send_from_buf(sm, t, dst); // send it - buffer_state[t] = BS_EMPTYING; - buffer_target[t] = -1; - sm->tx_state[dst] = t & 0x3; - } - // how about the one after that? - else if (buffer_target[t=sm->next_buf[t]] == dst){ // yes, - bsm12_send_from_buf(sm, t, dst); // send it - buffer_state[t] = BS_EMPTYING; - buffer_target[t] = -1; - sm->tx_state[dst] = t & 0x3; - } - else { - sm->tx_state[dst] = ST_IDLE; - } - } -} - -static void -bsm12_error_helper(bsm12_t *sm, int buf_this) -{ - bp_clear_buf(buf_this); // clears ERROR flag - - if (buffer_state[buf_this] == BS_FILLING){ - bsm12_receive_to_buf(sm, buf_this); // restart the xfer - } - else { // buffer was emptying - bsm12_resend_from_buf(sm, buf_this); // restart the xfer - } -} - - -void -bsm12_handle_tx_underrun(bsm12_t *sm) -{ -} - -void -bsm12_handle_rx_overrun(bsm12_t *sm) -{ -} diff --git a/firmware/microblaze/lib/bsm12.h b/firmware/microblaze/lib/bsm12.h deleted file mode 100644 index b8e576b79..000000000 --- a/firmware/microblaze/lib/bsm12.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2009 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef INCLUDED_BSM12_H -#define INCLUDED_BSM12_H - -#include "dbsm.h" -#include "memory_map.h" - -/*! - * buffer state machine: 1 input to two outputs - * - * Typically used to read packets from the ethernet and then after inspecting, - * handle the packet in firmware or pass it on to 1 of the 2 buffer destinations. - */ - -struct _bsm12; -typedef struct _bsm12 bsm12_t; - -/*! - * Pointer to function that does packet inspection. - * - * \param sm the state machine - * \param buf_this the index of the buffer to inspect and/or pass on - * - * Returns -1, 0 or 1. If it returns -1, it means that the s/w - * handled that packet, and that it should NOT be passed on to one of - * the buffer endpoints. 0 indicates the first endpoint, 1 the second endpoint. - */ -typedef int (*bsm12_inspector_t)(bsm12_t *sm, int buf_this); - - -/*! - * buffer state machine: 1 input to two outputs - */ -struct _bsm12 -{ - uint8_t buf0; // This machine uses buf0, buf0+1 and buf0+2. buf0 % 4 == 0. - uint8_t running; - int8_t rx_state; // -1, 0, 1, 2 which buffer we're receiving into - int8_t tx_state[2]; // -1, 0, 1, 2 which buffer we're sending from - buf_cmd_args_t recv_args; - buf_cmd_args_t send_args[2]; - bsm12_inspector_t inspect; - int last_line_adj; - uint32_t bps_error; - uint32_t bps_done; - uint32_t bps_error_or_done; - uint8_t next_buf[NBUFFERS]; - uint32_t precomputed_receive_to_buf_ctrl_word[3]; - uint32_t precomputed_send_from_buf_ctrl_word[4][2]; // really only 3, not 4 - // (easier addr comp) -}; - -void bsm12_init(bsm12_t *sm, int buf0, - const buf_cmd_args_t *recv, - const buf_cmd_args_t *send0, - const buf_cmd_args_t *send1, - bsm12_inspector_t inspect); - -void bsm12_start(bsm12_t *sm); -void bsm12_stop(bsm12_t *sm); -void bsm12_process_status(bsm12_t *sm, uint32_t status); -void bsm12_handle_tx_underrun(bsm12_t *sm); -void bsm12_handle_rx_overrun(bsm12_t *sm); - - -#endif /* INCLUDED_BSM12_H */ diff --git a/firmware/microblaze/lib/buffer_pool.c b/firmware/microblaze/lib/buffer_pool.c deleted file mode 100644 index 77e7c5213..000000000 --- a/firmware/microblaze/lib/buffer_pool.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "memory_map.h" -#include "buffer_pool.h" -#include "hal_io.h" - -void -bp_init(void) -{ - int i; - bp_disable_port(PORT_SERDES); - bp_disable_port(PORT_DSP); - bp_disable_port(PORT_ETH); - bp_disable_port(PORT_RAM); - - for (i = 0; i < NBUFFERS; i++) - bp_clear_buf(i); -} - -#ifndef INLINE_BUFFER_POOL - -void -bp_clear_buf(int bufnum) -{ - buffer_pool_ctrl->ctrl = BPC_BUFFER(bufnum) | BPC_PORT_NIL | BPC_CLR; -} - -void -bp_disable_port(int portnum) -{ - // disable buffer connections to this port - buffer_pool_ctrl->ctrl = BPC_BUFFER_NIL | BPC_PORT(portnum); -} - -void -bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll) -{ - buffer_pool_ctrl->ctrl = (BPC_READ - | BPC_BUFFER(bufnum) - | BPC_PORT(port) - | BPC_STEP(step) - | BPC_FIRST_LINE(fl) - | BPC_LAST_LINE(ll)); -} - -void -bp_send_from_buf(int bufnum, int port, int step, int fl, int ll) -{ - buffer_pool_ctrl->ctrl = (BPC_WRITE - | BPC_BUFFER(bufnum) - | BPC_PORT(port) - | BPC_STEP(step) - | BPC_FIRST_LINE(fl) - | BPC_LAST_LINE(ll)); -} - -#endif diff --git a/firmware/microblaze/lib/buffer_pool.h b/firmware/microblaze/lib/buffer_pool.h deleted file mode 100644 index 145b20f8d..000000000 --- a/firmware/microblaze/lib/buffer_pool.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef INCLUDED_BUFFER_POOL_H -#define INCLUDED_BUFFER_POOL_H - -#include "memory_map.h" - -// Buffer Pool Management - - -// define to have common buffer operations inlined -#define INLINE_BUFFER_POOL 1 - -void bp_init(void); - -#ifndef INLINE_BUFFER_POOL - -void bp_clear_buf(int bufnum); -void bp_disable_port(int portnum); -void bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll); -void bp_send_from_buf(int bufnum, int port, int step, int fl, int ll); - -#else - -static inline void -bp_clear_buf(int bufnum) -{ - buffer_pool_ctrl->ctrl = BPC_BUFFER(bufnum) | BPC_PORT_NIL | BPC_CLR; -} - -static inline void -bp_disable_port(int portnum) -{ - // disable buffer connections to this port - buffer_pool_ctrl->ctrl = BPC_BUFFER_NIL | BPC_PORT(portnum); -} - -static inline void -bp_receive_to_buf(int bufnum, int port, int step, int fl, int ll) -{ - buffer_pool_ctrl->ctrl = (BPC_READ - | BPC_BUFFER(bufnum) - | BPC_PORT(port) - | BPC_STEP(step) - | BPC_FIRST_LINE(fl) - | BPC_LAST_LINE(ll)); -} - -static inline void -bp_send_from_buf(int bufnum, int port, int step, int fl, int ll) -{ - buffer_pool_ctrl->ctrl = (BPC_WRITE - | BPC_BUFFER(bufnum) - | BPC_PORT(port) - | BPC_STEP(step) - | BPC_FIRST_LINE(fl) - | BPC_LAST_LINE(ll)); -} -#endif -#endif diff --git a/firmware/microblaze/lib/compiler.h b/firmware/microblaze/lib/compiler.h index 4fa9b49f8..f677bdc3b 100644 --- a/firmware/microblaze/lib/compiler.h +++ b/firmware/microblaze/lib/compiler.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009 Ettus Research LLC + * Copyright 2009, 2010 Ettus Research LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,5 +21,6 @@ // FIXME gcc specific. #define _AL4 __attribute__((aligned (4))) +#define FORCE_INLINE inline __attribute__((always_inline)) #endif /* INCLUDED_COMPILER_H */ diff --git a/firmware/microblaze/lib/dbsm.c b/firmware/microblaze/lib/dbsm.c deleted file mode 100644 index cee343eaa..000000000 --- a/firmware/microblaze/lib/dbsm.c +++ /dev/null @@ -1,299 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * Double Buffering State Machine - */ - -#include "dbsm.h" -#include "memory_map.h" -#include "buffer_pool.h" -#include <stdbool.h> -#include "nonstdio.h" -#include <stdlib.h> - -typedef enum { - BS_EMPTY, - BS_FILLING, - BS_FULL, - BS_EMPTYING, -} buffer_state_t; - -static buffer_state_t buffer_state[NBUFFERS]; - -bool -dbsm_nop_inspector(dbsm_t *sm, int buf_this) -{ - return false; -} - -void -dbsm_init(dbsm_t *sm, int buf0, - const buf_cmd_args_t *recv, const buf_cmd_args_t *send, - inspector_t inspect) -{ - if (buf0 & 0x1) // must be even - abort(); - - sm->buf0 = buf0; - sm->running = false; - sm->recv_args = *recv; - sm->send_args = *send; - - sm->rx_idle = true; - sm->tx_idle = true; - - sm->inspect = inspect; - - // How much to adjust the last_line register. - // It's 1 for everything but the ethernet. - //sm->last_line_adj = recv->port == PORT_ETH ? 3 : 1; - sm->last_line_adj = 1; - - buffer_state[sm->buf0] = BS_EMPTY; - buffer_state[sm->buf0 ^ 1] = BS_EMPTY; - - sm->precomputed_receive_to_buf_ctrl_word[0] = - (BPC_READ - | BPC_BUFFER(sm->buf0) - | BPC_PORT(sm->recv_args.port) - | BPC_STEP(1) - | BPC_FIRST_LINE(sm->recv_args.first_line) - | BPC_LAST_LINE(sm->recv_args.last_line)); - - sm->precomputed_receive_to_buf_ctrl_word[1] = - (BPC_READ - | BPC_BUFFER(sm->buf0 ^ 1) - | BPC_PORT(sm->recv_args.port) - | BPC_STEP(1) - | BPC_FIRST_LINE(sm->recv_args.first_line) - | BPC_LAST_LINE(sm->recv_args.last_line)); - - sm->precomputed_send_from_buf_ctrl_word[0] = - (BPC_WRITE - | BPC_BUFFER(sm->buf0) - | BPC_PORT(sm->send_args.port) - | BPC_STEP(1) - | BPC_FIRST_LINE(sm->send_args.first_line) - | BPC_LAST_LINE(0)); // last line filled in at runtime - - sm->precomputed_send_from_buf_ctrl_word[1] = - (BPC_WRITE - | BPC_BUFFER(sm->buf0 ^ 1) - | BPC_PORT(sm->send_args.port) - | BPC_STEP(1) - | BPC_FIRST_LINE(sm->send_args.first_line) - | BPC_LAST_LINE(0)); // last line filled in at runtime - -} - -static inline void -dbsm_receive_to_buf(dbsm_t *sm, int bufno) -{ - buffer_pool_ctrl->ctrl = sm->precomputed_receive_to_buf_ctrl_word[bufno & 1]; -} - -static inline void -dbsm_send_from_buf(dbsm_t *sm, int bufno) -{ - buffer_pool_ctrl->ctrl = - (sm->precomputed_send_from_buf_ctrl_word[bufno & 1] - | BPC_LAST_LINE(buffer_pool_status->last_line[bufno] - sm->last_line_adj)); -} - -void -dbsm_start(dbsm_t *sm) -{ - // printf("dbsm_start: buf0 = %d, recv_port = %d\n", sm->buf0, sm->recv_args.port); - - sm->running = true; - - buffer_state[sm->buf0] = BS_EMPTY; - buffer_state[sm->buf0 ^ 1] = BS_EMPTY; - - bp_clear_buf(sm->buf0); - bp_clear_buf(sm->buf0 ^ 1); - - sm->tx_idle = true; - sm->rx_idle = false; - dbsm_receive_to_buf(sm, sm->buf0); - buffer_state[sm->buf0] = BS_FILLING; - -} - - -void -dbsm_stop(dbsm_t *sm) -{ - sm->running = false; - bp_clear_buf(sm->buf0); - bp_clear_buf(sm->buf0 ^ 1); - buffer_state[sm->buf0] = BS_EMPTY; - buffer_state[sm->buf0 ^ 1] = BS_EMPTY; -} - -static void dbsm_process_helper(dbsm_t *sm, int buf_this); -static void dbsm_error_helper(dbsm_t *sm, int buf_this); - -void -dbsm_process_status(dbsm_t *sm, uint32_t status) -{ - if (!sm->running) - return; - - if (status & (BPS_ERROR(sm->buf0) | BPS_ERROR(sm->buf0 ^ 1))){ - putchar('E'); - // Most likely an ethernet Rx error. We just restart the transfer. - if (status & (BPS_ERROR(sm->buf0))) - dbsm_error_helper(sm, sm->buf0); - //dbsm_process_helper(sm, sm->buf0); //forward errors - - if (status & (BPS_ERROR(sm->buf0 ^ 1))) - dbsm_error_helper(sm, sm->buf0 ^ 1); - //dbsm_process_helper(sm, sm->buf0 ^ 1); //forward errors - } - - if (status & BPS_DONE(sm->buf0)) - dbsm_process_helper(sm, sm->buf0); - - if (status & BPS_DONE(sm->buf0 ^ 1)) - dbsm_process_helper(sm, sm->buf0 ^ 1); -} - -static void -dbsm_process_helper(dbsm_t *sm, int buf_this) -{ - int buf_other = buf_this ^ 1; - - bp_clear_buf(buf_this); - - if (buffer_state[buf_this] == BS_FILLING){ - buffer_state[buf_this] = BS_FULL; - // - // does s/w handle this packet? - // - if (sm->inspect(sm, buf_this)){ - // s/w handled the packet; refill the buffer - dbsm_receive_to_buf(sm, buf_this); - buffer_state[buf_this] = BS_FILLING; - } - - else { // s/w didn't handle this; pass it on - - if(buffer_state[buf_other] == BS_EMPTY){ - dbsm_receive_to_buf(sm, buf_other); - buffer_state[buf_other] = BS_FILLING; - } - else - sm->rx_idle = true; - - if (sm->tx_idle){ - sm->tx_idle = false; - dbsm_send_from_buf(sm, buf_this); - buffer_state[buf_this] = BS_EMPTYING; - } - } - } - else { // buffer was emptying - buffer_state[buf_this] = BS_EMPTY; - if (sm->rx_idle){ - sm->rx_idle = false; - dbsm_receive_to_buf(sm, buf_this); - buffer_state[buf_this] = BS_FILLING; - } - if (buffer_state[buf_other] == BS_FULL){ - dbsm_send_from_buf(sm, buf_other); - buffer_state[buf_other] = BS_EMPTYING; - } - else - sm->tx_idle = true; - } -} - -static void -dbsm_error_helper(dbsm_t *sm, int buf_this) -{ - bp_clear_buf(buf_this); // clears ERROR flag - - if (buffer_state[buf_this] == BS_FILLING){ - dbsm_receive_to_buf(sm, buf_this); // restart the xfer - } - else { // buffer was emptying - dbsm_send_from_buf(sm, buf_this); // restart the xfer - } -} - -/* - * Handle DSP Tx underrun - */ -void -dbsm_handle_tx_underrun(dbsm_t *sm) -{ - // clear the DSP Tx state machine - sr_tx_ctrl->clear_state = 1; - - // If there's a buffer that's empyting, clear it & flush xfer - - if (buffer_state[sm->buf0] == BS_EMPTYING){ - bp_clear_buf(sm->buf0); - sr_tx_ctrl->clear_state = 1; // flush partial packet - // drop frame in progress on ground. Pretend it finished - dbsm_process_helper(sm, sm->buf0); - } - else if (buffer_state[sm->buf0 ^ 1] == BS_EMPTYING){ - bp_clear_buf(sm->buf0 ^ 1); - sr_tx_ctrl->clear_state = 1; // flush partial packet - // drop frame in progress on ground. Pretend it finished - dbsm_process_helper(sm, sm->buf0 ^ 1); - } -} - -/* - * Handle DSP Rx overrun - */ -void -dbsm_handle_rx_overrun(dbsm_t *sm) -{ - sr_rx_ctrl->clear_overrun = 1; - - // If there's a buffer that's filling, clear it. - // Any restart will be the job of the caller. - - if (buffer_state[sm->buf0] == BS_FILLING) - bp_clear_buf(sm->buf0); - - if (buffer_state[sm->buf0 ^1] == BS_FILLING) - bp_clear_buf(sm->buf0 ^ 1); -} - -void -dbsm_wait_for_opening(dbsm_t *sm) -{ - if (buffer_state[sm->buf0] == BS_EMPTYING){ - // wait for xfer to complete - int mask = BPS_DONE(sm->buf0) | BPS_ERROR(sm->buf0) | BPS_IDLE(sm->buf0); - while ((buffer_pool_status->status & mask) == 0) - ; - } - else if (buffer_state[sm->buf0 ^ 1] == BS_EMPTYING){ - // wait for xfer to complete - int mask = BPS_DONE(sm->buf0 ^ 1) | BPS_ERROR(sm->buf0 ^ 1) | BPS_IDLE(sm->buf0 ^ 1); - while ((buffer_pool_status->status & mask) == 0) - ; - } -} diff --git a/firmware/microblaze/lib/dbsm.h b/firmware/microblaze/lib/dbsm.h deleted file mode 100644 index cb7e12fc3..000000000 --- a/firmware/microblaze/lib/dbsm.h +++ /dev/null @@ -1,90 +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_DBSM_H -#define INCLUDED_DBSM_H - -/* - * Double Buffering State Machine - */ - -#include <stdint.h> -#include <stdbool.h> - -struct _dbsm; -typedef struct _dbsm dbsm_t; - -/* - * pointer to function that does packet inspection. - * - * If one of these returns true, it means that the s/w - * handled that packet, and that it should NOT be passed - * on to the normal destination port. - */ -typedef bool (*inspector_t)(dbsm_t *sm, int buf_this); - -bool dbsm_nop_inspector(dbsm_t *sm, int buf_this); // returns false - - -typedef struct -{ - uint16_t port; - uint16_t first_line; - uint16_t last_line; -} buf_cmd_args_t; - -/*! - * double buffer state machine - */ -struct _dbsm -{ - uint8_t buf0; // Must be even. This machine uses buf0 and buf0+1 - uint8_t running; - uint8_t rx_idle; - uint8_t tx_idle; - buf_cmd_args_t recv_args; - buf_cmd_args_t send_args; - inspector_t inspect; - uint32_t precomputed_receive_to_buf_ctrl_word[2]; - uint32_t precomputed_send_from_buf_ctrl_word[2]; - int last_line_adj; -}; - -void dbsm_init(dbsm_t *sm, int buf0, - const buf_cmd_args_t *recv, const buf_cmd_args_t *send, - inspector_t inspect); - -void dbsm_start(dbsm_t *sm); -void dbsm_stop(dbsm_t *sm); -void dbsm_process_status(dbsm_t *sm, uint32_t status); -void dbsm_handle_tx_underrun(dbsm_t *sm); -void dbsm_handle_rx_overrun(dbsm_t *sm); - -/* - * The cpu calls this when it want to ensure that it can send a buffer - * to the same destination being used by this state machine. - * - * If neither buffer is EMPTYING it returns immediately. If a buffer - * is EMPYTING, it waits for the h/w to transition to the DONE or - * ERROR state. - * - * When this function returns, the caller queues it's buffer and busy - * waits for it to complete. - */ -void dbsm_wait_for_opening(dbsm_t *sm); - -#endif /* INCLUDED_DBSM_H */ diff --git a/firmware/microblaze/lib/eth_mac.c b/firmware/microblaze/lib/eth_mac.c index 034a4d494..581a5c69f 100644 --- a/firmware/microblaze/lib/eth_mac.c +++ b/firmware/microblaze/lib/eth_mac.c @@ -28,6 +28,7 @@ void eth_mac_set_addr(const eth_mac_addr_t *src) { + /* disable because MAC_SET_PASS_ALL is set below eth_mac->ucast_hi = (((unsigned int)src->addr[0])<<8) + ((unsigned int)src->addr[1]); @@ -36,6 +37,7 @@ eth_mac_set_addr(const eth_mac_addr_t *src) (((unsigned int)src->addr[3])<<16) + (((unsigned int)src->addr[4])<<8) + (((unsigned int)src->addr[5])); +*/ } @@ -45,7 +47,7 @@ eth_mac_init(const eth_mac_addr_t *src) eth_mac->miimoder = 25; // divider from CPU clock (50MHz/25 = 2MHz) eth_mac_set_addr(src); - eth_mac->settings = MAC_SET_PAUSE_EN | MAC_SET_PASS_BCAST | MAC_SET_PASS_UCAST | MAC_SET_PAUSE_SEND_EN; + eth_mac->settings = MAC_SET_PAUSE_EN | MAC_SET_PASS_BCAST | MAC_SET_PASS_UCAST | MAC_SET_PAUSE_SEND_EN | MAC_SET_PASS_ALL; eth_mac->pause_time = 38; eth_mac->pause_thresh = 1200; diff --git a/firmware/microblaze/lib/net_common.c b/firmware/microblaze/lib/net_common.c index 6305408d6..a34ca615b 100644 --- a/firmware/microblaze/lib/net_common.c +++ b/firmware/microblaze/lib/net_common.c @@ -22,7 +22,6 @@ #include "net_common.h" #include "banal.h" #include <hal_io.h> -#include <buffer_pool.h> #include <memory_map.h> #include <memcpy_wa.h> #include <ethernet.h> @@ -36,28 +35,21 @@ #include "if_arp.h" #include <ethertype.h> #include <string.h> +#include "pkt_ctrl.h" +static const bool debug = false; -int cpu_tx_buf_dest_port = PORT_ETH; +static const eth_mac_addr_t BCAST_MAC_ADDR = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; -// If this is non-zero, this dbsm could be writing to the ethernet -dbsm_t *ac_could_be_sending_to_eth; - -static inline bool -ip_addr_eq(const struct ip_addr a, const struct ip_addr b) -{ - return a.addr == b.addr; -} +//used in the top level application... +struct socket_address fp_socket_src, fp_socket_dst; // ------------------------------------------------------------------------ static eth_mac_addr_t _local_mac_addr; -void register_mac_addr(const eth_mac_addr_t *mac_addr){ - _local_mac_addr = *mac_addr; -} - static struct ip_addr _local_ip_addr; -void register_ip_addr(const struct ip_addr *ip_addr){ +void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_addr){ + _local_mac_addr = *mac_addr; _local_ip_addr = *ip_addr; } @@ -126,13 +118,6 @@ send_pkt(eth_mac_addr_t dst, int ethertype, const void *buf1, size_t len1, const void *buf2, size_t len2) { - // Wait for buffer to become idle - // FIXME can this ever not be ready? - - //hal_set_leds(LED_BUF_BUSY, LED_BUF_BUSY); - while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0) - ; - //hal_set_leds(0, LED_BUF_BUSY); // Assemble the header padded_eth_hdr_t ehdr; @@ -141,9 +126,10 @@ send_pkt(eth_mac_addr_t dst, int ethertype, ehdr.src = _local_mac_addr; ehdr.ethertype = ethertype; - uint32_t *p = buffer_ram(CPU_TX_BUF); + uint32_t *buff = (uint32_t *)pkt_ctrl_claim_outgoing_buffer(); // Copy the pieces into the buffer + uint32_t *p = buff; *p++ = 0x0; // slow path memcpy_wa(p, &ehdr, sizeof(ehdr)); // 4 lines p += sizeof(ehdr)/sizeof(uint32_t); @@ -173,34 +159,23 @@ send_pkt(eth_mac_addr_t dst, int ethertype, p += len2/sizeof(uint32_t); } - size_t total_len = (p - buffer_ram(CPU_TX_BUF)) * sizeof(uint32_t); + size_t total_len = (p - buff) * sizeof(uint32_t); if (total_len < 60) // ensure that we don't try to send a short packet total_len = 60; - - // wait until nobody else is sending to the ethernet - if (ac_could_be_sending_to_eth){ - //hal_set_leds(LED_ETH_BUSY, LED_ETH_BUSY); - dbsm_wait_for_opening(ac_could_be_sending_to_eth); - //hal_set_leds(0x0, LED_ETH_BUSY); - } - - if (0){ - printf("send_pkt to port %d, len = %d\n", - cpu_tx_buf_dest_port, (int) total_len); - print_buffer(buffer_ram(CPU_TX_BUF), total_len/4); - } - - // fire it off - bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 1, 0, total_len/4); - // wait for it to complete (not long, it's a small pkt) - while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) | BPS_ERROR(CPU_TX_BUF))) == 0) - ; + pkt_ctrl_commit_outgoing_buffer(total_len/4); + if (debug) printf("sent %d bytes\n", (int)total_len); +} - bp_clear_buf(CPU_TX_BUF); +unsigned int CHKSUM(unsigned int x, unsigned int *chksum) +{ + *chksum += x; + *chksum = (*chksum & 0xffff) + (*chksum>>16); + *chksum = (*chksum & 0xffff) + (*chksum>>16); + return x; } -unsigned int +static unsigned int chksum_buffer(unsigned short *buf, int nshorts, unsigned int initial_chksum) { unsigned int chksum = initial_chksum; @@ -210,7 +185,6 @@ chksum_buffer(unsigned short *buf, int nshorts, unsigned int initial_chksum) return chksum; } - void send_ip_pkt(struct ip_addr dst, int protocol, const void *buf0, size_t len0, @@ -235,7 +209,7 @@ send_ip_pkt(struct ip_addr dst, int protocol, bool found = arp_cache_lookup_mac(&ip.dest, &dst_mac); if (!found){ printf("net_common: failed to hit cache looking for "); - print_ip(ip.dest); + print_ip_addr(&ip.dest); newline(); return; } @@ -294,6 +268,11 @@ handle_icmp_packet(struct ip_addr src, struct ip_addr dst, if (icmp->code == ICMP_DUR_PORT){ // port unreachable //handle destination port unreachable (the host ctrl+c'd the app): + //filter out non udp data response + struct ip_hdr *ip = (struct ip_hdr *)(((uint8_t*)icmp) + sizeof(struct icmp_echo_hdr)); + struct udp_hdr *udp = (struct udp_hdr *)(((char *)ip) + IP_HLEN); + if (IPH_PROTO(ip) != IP_PROTO_UDP || udp->dest != fp_socket_dst.port) return; + //end async update packets per second sr_tx_ctrl->cyc_per_up = 0; @@ -373,8 +352,7 @@ void send_gratuitous_arp(void){ memcpy(req.ar_tip, get_ip_addr(), sizeof(struct ip_addr)); //send the request with a broadcast ethernet mac address - eth_mac_addr_t t; memset(&t, 0xff, sizeof(t)); - send_pkt(t, ETHERTYPE_ARP, &req, sizeof(req), 0, 0, 0, 0); + send_pkt(BCAST_MAC_ADDR, ETHERTYPE_ARP, &req, sizeof(req), 0, 0, 0, 0); } static void @@ -412,7 +390,7 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size) sip.addr = get_int32(p->ar_sip); tip.addr = get_int32(p->ar_tip); - if (ip_addr_eq(tip, _local_ip_addr)){ // They're looking for us... + if (memcmp(&tip, &_local_ip_addr, sizeof(_local_ip_addr)) == 0){ // They're looking for us... send_arp_reply(p, _local_mac_addr); } } @@ -420,15 +398,17 @@ handle_arp_packet(struct arp_eth_ipv4 *p, size_t size) void handle_eth_packet(uint32_t *p, size_t nlines) { - //print_buffer(p, nlines); + static size_t bcount = 0; + if (debug) printf("===> %d\n", (int)bcount++); + if (debug) print_buffer(p, nlines); - int ethertype = p[3] & 0xffff; + padded_eth_hdr_t *eth_hdr = (padded_eth_hdr_t *)p; - if (ethertype == ETHERTYPE_ARP){ + if (eth_hdr->ethertype == ETHERTYPE_ARP){ struct arp_eth_ipv4 *arp = (struct arp_eth_ipv4 *)(p + 4); handle_arp_packet(arp, nlines*sizeof(uint32_t) - 14); } - else if (ethertype == ETHERTYPE_IPV4){ + else if (eth_hdr->ethertype == ETHERTYPE_IPV4){ struct ip_hdr *ip = (struct ip_hdr *)(p + 4); if (IPH_V(ip) != 4 || IPH_HL(ip) != 5) // ignore pkts w/ bad version or options return; @@ -436,7 +416,10 @@ handle_eth_packet(uint32_t *p, size_t nlines) if (IPH_OFFSET(ip) & (IP_MF | IP_OFFMASK)) // ignore fragmented packets return; - // FIXME filter on dest ip addr (should be broadcast or for us) + // filter on dest ip addr (should be broadcast or for us) + bool is_bcast = memcmp(ð_hdr->dst, &BCAST_MAC_ADDR, sizeof(BCAST_MAC_ADDR)) == 0; + bool is_my_ip = memcmp(&ip->dest, &_local_ip_addr, sizeof(_local_ip_addr)) == 0; + if (!is_bcast && !is_my_ip) return; arp_cache_update(&ip->src, (eth_mac_addr_t *)(((char *)p)+8)); diff --git a/firmware/microblaze/lib/net_common.h b/firmware/microblaze/lib/net_common.h index 3040e5ef3..4004ca6e6 100644 --- a/firmware/microblaze/lib/net_common.h +++ b/firmware/microblaze/lib/net_common.h @@ -20,25 +20,20 @@ #include <stdint.h> #include <stddef.h> -#include <dbsm.h> #include <net/socket_address.h> #include <net/eth_mac_addr.h> -#define CPU_TX_BUF 7 // cpu -> eth - -extern int cpu_tx_buf_dest_port; - -// If this is non-zero, this dbsm could be writing to the ethernet -extern dbsm_t *ac_could_be_sending_to_eth; - -void stop_streaming(void); +/* + * 1's complement sum for IP and UDP headers + * + * init chksum to zero to start. + */ +unsigned int CHKSUM(unsigned int x, unsigned int *chksum); typedef void (*udp_receiver_t)(struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len); -void register_mac_addr(const eth_mac_addr_t *mac_addr); - -void register_ip_addr(const struct ip_addr *ip_addr); +void register_addrs(const eth_mac_addr_t *mac_addr, const struct ip_addr *ip_addr); void register_udp_listener(int port, udp_receiver_t rcvr); diff --git a/firmware/microblaze/lib/nonstdio.h b/firmware/microblaze/lib/nonstdio.h index 62ebfa46d..6aca7ed9a 100644 --- a/firmware/microblaze/lib/nonstdio.h +++ b/firmware/microblaze/lib/nonstdio.h @@ -45,4 +45,6 @@ void print_buffer(uint32_t *buf, size_t n); //char *itoa(signed long value, char *result, int base); //void reverse(char s[]); +void print_ip_addr(const void *t); + #endif /* INCLUDED_NONSTDIO_H */ diff --git a/firmware/microblaze/lib/pkt_ctrl.c b/firmware/microblaze/lib/pkt_ctrl.c new file mode 100644 index 000000000..7e095ec00 --- /dev/null +++ b/firmware/microblaze/lib/pkt_ctrl.c @@ -0,0 +1,69 @@ +/* + * Copyright 2010 Ettus Research LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "pkt_ctrl.h" +#include "memory_map.h" +#include <nonstdio.h> + +void pkt_ctrl_program_inspector( + const struct ip_addr *ip_addr, uint16_t ctrl_port, uint16_t data_port +){ + buffer_pool_ctrl->ip_addr = ip_addr->addr; + buffer_pool_ctrl->ctrl_ports = ctrl_port; + buffer_pool_ctrl->data_ports = data_port; +} + +void pkt_ctrl_set_routing_mode(pkt_ctrl_routing_mode_t mode){ + switch(mode){ + case PKT_CTRL_ROUTING_MODE_SLAVE: + buffer_pool_ctrl->misc_ctrl = 0; + break; + case PKT_CTRL_ROUTING_MODE_MASTER: + buffer_pool_ctrl->misc_ctrl = 1; + break; + } +} + +static inline bool is_status_bit_set(int bit){ + return buffer_pool_status->status & (1 << bit); +} + +#define CPU_OUT_HS_BIT 0 //from packet router to CPU +#define CPU_INP_HS_BIT 1 //from CPU to packet router + +void *pkt_ctrl_claim_incoming_buffer(size_t *num_lines){ + if (!is_status_bit_set(CPU_OUT_HS_BIT)) return NULL; + *num_lines = (buffer_pool_status->status >> 16) & 0xffff; + return buffer_ram(0); +} + +void pkt_ctrl_release_incoming_buffer(void){ + buffer_pool_ctrl->cpu_out_ctrl = 1; + while (is_status_bit_set(CPU_OUT_HS_BIT)){} + buffer_pool_ctrl->cpu_out_ctrl = 0; +} + +void *pkt_ctrl_claim_outgoing_buffer(void){ + while (!is_status_bit_set(CPU_INP_HS_BIT)){} + return buffer_ram(1); +} + +void pkt_ctrl_commit_outgoing_buffer(size_t num_lines){ + buffer_pool_ctrl->cpu_inp_ctrl = ((num_lines & 0xffff) << 16) | 1; + while (is_status_bit_set(CPU_INP_HS_BIT)){} + buffer_pool_ctrl->cpu_inp_ctrl = 0; +} diff --git a/firmware/microblaze/lib/pkt_ctrl.h b/firmware/microblaze/lib/pkt_ctrl.h new file mode 100644 index 000000000..346e22094 --- /dev/null +++ b/firmware/microblaze/lib/pkt_ctrl.h @@ -0,0 +1,63 @@ +/* + * Copyright 2010 Ettus Research LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef INCLUDED_PKT_CTRL_H +#define INCLUDED_PKT_CTRL_H + +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> +#include <lwip/ip_addr.h> + +typedef enum { + PKT_CTRL_ROUTING_MODE_SLAVE, + PKT_CTRL_ROUTING_MODE_MASTER, +} pkt_ctrl_routing_mode_t; + +//! Program the decision values into the packet inspector +void pkt_ctrl_program_inspector( + const struct ip_addr *ip_addr, uint16_t ctrl_port, uint16_t data_port +); + +//! Set the routing mode for this device +void pkt_ctrl_set_routing_mode(pkt_ctrl_routing_mode_t mode); + +/*! + * Try to claim an incomming buffer. + * \param num_lines filled with the buffer size + * \return a pointer to the buffer memory or NULL + */ +void *pkt_ctrl_claim_incoming_buffer(size_t *num_lines); + +/*! + * Release the incoming buffer. Call when done. + */ +void pkt_ctrl_release_incoming_buffer(void); + +/*! + * Claim an outgoing buffer. + * \return a pointer to the buffer + */ +void *pkt_ctrl_claim_outgoing_buffer(void); + +/*! + * Commit the outgoing buffer. + * \param num_lines how many lines written. + */ +void pkt_ctrl_commit_outgoing_buffer(size_t num_lines); + +#endif /* INCLUDED_PKT_CTRL_H */ diff --git a/firmware/microblaze/lib/print_mac_addr.c b/firmware/microblaze/lib/print_addrs.c index 475082325..29601c47c 100644 --- a/firmware/microblaze/lib/print_mac_addr.c +++ b/firmware/microblaze/lib/print_addrs.c @@ -26,3 +26,7 @@ print_mac_addr(const unsigned char addr[6]) } } +void print_ip_addr(const void *t){ + uint8_t *p = (uint8_t *)t; + printf("%d.%d.%d.%d", p[0], p[1], p[2], p[3]); +} diff --git a/firmware/microblaze/lib/spi.c b/firmware/microblaze/lib/spi.c index 2a41a1bfa..af0d8a68f 100644 --- a/firmware/microblaze/lib/spi.c +++ b/firmware/microblaze/lib/spi.c @@ -20,9 +20,9 @@ #include "pic.h" #include "nonstdio.h" -void (*volatile spi_callback)(void); //SPI callback when xfer complete. +//void (*volatile spi_callback)(void); //SPI callback when xfer complete. -static void spi_irq_handler(unsigned irq); +//static void spi_irq_handler(unsigned irq); void spi_init(void) @@ -66,6 +66,7 @@ spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags return 0; } +/* void spi_register_callback(void (*volatile callback)(void)) { spi_callback = callback; } @@ -106,3 +107,4 @@ spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (* return true; } +*/ diff --git a/firmware/microblaze/lib/spi.h b/firmware/microblaze/lib/spi.h index 54618cedd..71245150a 100644 --- a/firmware/microblaze/lib/spi.h +++ b/firmware/microblaze/lib/spi.h @@ -48,12 +48,12 @@ void spi_wait(void); uint32_t spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags); -uint32_t spi_get_data(void); +//uint32_t spi_get_data(void); //static void spi_irq_handler(unsigned irq); -void spi_register_callback(void (*volatile callback)(void)); +//void spi_register_callback(void (*volatile callback)(void)); -bool -spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void)); +//bool +//spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void)); // ---------------------------------------------------------------- // Routines that manipulate the FLASH SPI BUS diff --git a/firmware/microblaze/lib/u2_init.c b/firmware/microblaze/lib/u2_init.c index 4a553a713..191a0e816 100644 --- a/firmware/microblaze/lib/u2_init.c +++ b/firmware/microblaze/lib/u2_init.c @@ -20,25 +20,13 @@ #include "spi.h" #include "pic.h" #include "hal_io.h" -#include "buffer_pool.h" #include "hal_uart.h" #include "i2c.h" -#include "i2c_async.h" #include "mdelay.h" #include "clocks.h" #include "usrp2/fw_common.h" #include "nonstdio.h" -unsigned char u2_hw_rev_major; -unsigned char u2_hw_rev_minor; - -static inline void -get_hw_rev(void) -{ - bool ok = eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV, &u2_hw_rev_minor, 1); - ok &= eeprom_read(USRP2_I2C_ADDR_MBOARD, USRP2_EE_MBOARD_REV+1, &u2_hw_rev_major, 1); -} - /* * We ought to arrange for this to be called before main, but for now, * we require that the user's main call u2_init as the first thing... @@ -60,13 +48,8 @@ u2_init(void) // init i2c so we can read our rev pic_init(); // progammable interrupt controller i2c_init(); - i2c_register_handler(); //for using async I2C hal_enable_ints(); - bp_init(); // buffer pool - - - // flash all leds to let us know board is alive hal_set_leds(0x0, 0x1f); mdelay(100); @@ -85,6 +68,8 @@ u2_init(void) printf("ad9510 reg[0x%x] = 0x%x\n", rr, vv); } #endif - + + output_regs->serdes_ctrl = (SERDES_ENABLE | SERDES_RXEN); + return true; } diff --git a/firmware/microblaze/lib/usrp2_bytesex.h b/firmware/microblaze/lib/usrp2_bytesex.h deleted file mode 100644 index 2b74f2a0b..000000000 --- a/firmware/microblaze/lib/usrp2_bytesex.h +++ /dev/null @@ -1,66 +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_USRP2_BYTESEX_H -#define INCLUDED_USRP2_BYTESEX_H - -// The USRP2 speaks big-endian... -// Use the standard include files or provide substitutions for -// htons and friends - -#if defined(HAVE_ARPA_INET_H) -#include <arpa/inet.h> -#elif defined(HAVE_NETINET_IN_H) -#include <netinet/in.h> -#else -#include <stdint.h> - -#ifdef WORDS_BIGENDIAN // nothing to do... - -static inline uint32_t htonl(uint32_t x){ return x; } -static inline uint16_t htons(uint16_t x){ return x; } -static inline uint32_t ntohl(uint32_t x){ return x; } -static inline uint16_t ntohs(uint16_t x){ return x; } - -#else - -#ifdef HAVE_BYTESWAP_H -#include <byteswap.h> -#else - -static inline uint16_t -bswap_16 (uint16_t x) -{ - return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)); -} - -static inline uint32_t -bswap_32 (uint32_t x) -{ - return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ - | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)); -} -#endif - -static inline uint32_t htonl(uint32_t x){ return bswap_32(x); } -static inline uint16_t htons(uint16_t x){ return bswap_16(x); } -static inline uint32_t ntohl(uint32_t x){ return bswap_32(x); } -static inline uint16_t ntohs(uint16_t x){ return bswap_16(x); } - -#endif -#endif -#endif /* INCLUDED_USRP2_BYTESEX_H */ diff --git a/firmware/microblaze/lib/wb16550.h b/firmware/microblaze/lib/wb16550.h deleted file mode 100644 index 7522f4438..000000000 --- a/firmware/microblaze/lib/wb16550.h +++ /dev/null @@ -1,98 +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/>. - */ - - -// Wishbone National Semiconductor 16550A compatible UART - -#ifndef INCLUDED_WB16550_H -#define INCLUDED_WB16550_H - -#include <stdint.h> - -typedef struct { - volatile uint8_t data; // 0 r/w: r: rx fifo, w: tx fifo (if DLAB: LSB of divisor) - volatile uint8_t ier; // 1 r/w: Interrupt Enable Register (if DLAB: MSB of divisor) - volatile uint8_t iir_fcr; // 2 r/w: r: Interrupt ID Register, - // w: Fifo Control Register - volatile uint8_t lcr; // 3 r/w: Line Control Register - volatile uint8_t mcr; // 4 w: Modem Control Register - volatile uint8_t lsr; // 5 r: Line Status Register - volatile uint8_t msr; // 6 r: Modem Status Register - -} wb16550_reg_t; - -#define UART_IER_RDI 0x01 // Enable received data interrupt -#define UART_IER_THRI 0x02 // Enable transmitter holding reg empty int. -#define UART_IER_RLSI 0x04 // Enable receiver line status interrupt -#define UART_IER_MSI 0x08 // Enable modem status interrupt - -#define UART_IIR_NO_INT 0x01 // No interrupts pending -#define UART_IIR_ID_MASK 0x06 // Mask for interrupt ID -#define UART_IIR_MSI 0x00 // Modem status interrupt -#define UART_IIR_THRI 0x02 // Tx holding register empty int -#define UART_IIR_RDI 0x04 // Rx data available int -#define UART_IIR_RLSI 0x06 // Receiver line status int - -#define UART_FCR_ENABLE_FIFO 0x01 // ignore, always enabled -#define UART_FCR_CLEAR_RCVR 0x02 // Clear the RCVR FIFO -#define UART_FCR_CLEAR_XMIT 0x04 // Clear the XMIT FIFO -#define UART_FCR_TRIGGER_MASK 0xC0 // Mask for FIFO trigger range -#define UART_FCR_TRIGGER_1 0x00 // Rx fifo trigger level: 1 byte -#define UART_FCR_TRIGGER_4 0x40 // Rx fifo trigger level: 4 bytes -#define UART_FCR_TRIGGER_8 0x80 // Rx fifo trigger level: 8 bytes -#define UART_FCR_TRIGGER_14 0xC0 // Rx fifo trigger level: 14 bytes - -#define UART_LCR_DLAB 0x80 // Divisor latch access bit -#define UART_LCR_SBC 0x40 // Set break control -#define UART_LCR_SPAR 0x20 // Stick parity -#define UART_LCR_EPAR 0x10 // Even parity select -#define UART_LCR_PARITY 0x08 // Parity Enable -#define UART_LCR_STOP 0x04 // Stop bits: 0=1 bit, 1=2 bits -#define UART_LCR_WLEN5 0x00 // Wordlength: 5 bits -#define UART_LCR_WLEN6 0x01 // Wordlength: 6 bits -#define UART_LCR_WLEN7 0x02 // Wordlength: 7 bits -#define UART_LCR_WLEN8 0x03 // Wordlength: 8 bits - -#define UART_MCR_LOOP 0x10 // Enable loopback test mode -#define UART_MCR_OUT2n 0x08 // Out2 complement (loopback mode) -#define UART_MCR_OUT1n 0x04 // Out1 complement (loopback mode) -#define UART_MCR_RTSn 0x02 // RTS complement -#define UART_MCR_DTRn 0x01 // DTR complement - -#define UART_LSR_TEMT 0x40 // Transmitter empty -#define UART_LSR_THRE 0x20 // Transmit-hold-register empty -#define UART_LSR_BI 0x10 // Break interrupt indicator -#define UART_LSR_FE 0x08 // Frame error indicator -#define UART_LSR_PE 0x04 // Parity error indicator -#define UART_LSR_OE 0x02 // Overrun error indicator -#define UART_LSR_DR 0x01 // Receiver data ready -#define UART_LSR_BRK_ERROR_BITS 0x1E // BI, FE, PE, OE bits -#define UART_LSR_ERROR 0x80 // At least 1 PE, FE or BI are in the fifo - -#define UART_MSR_DCD 0x80 // Data Carrier Detect -#define UART_MSR_RI 0x40 // Ring Indicator -#define UART_MSR_DSR 0x20 // Data Set Ready -#define UART_MSR_CTS 0x10 // Clear to Send -#define UART_MSR_DDCD 0x08 // Delta DCD -#define UART_MSR_TERI 0x04 // Trailing edge ring indicator -#define UART_MSR_DDSR 0x02 // Delta DSR -#define UART_MSR_DCTS 0x01 // Delta CTS -#define UART_MSR_ANY_DELTA 0x0F // Any of the delta bits! - - -#endif // INCLUDED_WB16550_H diff --git a/firmware/microblaze/usrp2/Makefile.am b/firmware/microblaze/usrp2/Makefile.am index 7a58e7253..7fd353204 100644 --- a/firmware/microblaze/usrp2/Makefile.am +++ b/firmware/microblaze/usrp2/Makefile.am @@ -24,8 +24,6 @@ AM_LDFLAGS = \ $(COMMON_LFLAGS) \ -Wl,-defsym -Wl,_TEXT_START_ADDR=0x0050 \ -Wl,-defsym -Wl,_STACK_SIZE=3072 - -LDADD = libusrp2.a LDADD = libusrp2.a @@ -38,7 +36,7 @@ libusrp2_a_SOURCES = \ $(COMMON_SRCS) \ sd.c \ ethernet.c \ - udp_fw_update.c + udp_fw_update.c noinst_PROGRAMS = \ usrp2_txrx_uhd.elf diff --git a/firmware/microblaze/usrp2/memory_map.h b/firmware/microblaze/usrp2/memory_map.h index eac0c217f..23d96389f 100644 --- a/firmware/microblaze/usrp2/memory_map.h +++ b/firmware/microblaze/usrp2/memory_map.h @@ -53,9 +53,7 @@ #define BUFFER_POOL_RAM_BASE 0x8000 -#define NBUFFERS 8 #define BP_NLINES 0x0200 // number of 32-bit lines in a buffer -#define BP_LAST_LINE (BP_NLINES - 1) // last line in a buffer #define buffer_pool_ram \ ((uint32_t *) BUFFER_POOL_RAM_BASE) @@ -173,8 +171,8 @@ typedef struct { #define BUFFER_POOL_STATUS_BASE 0xCC00 typedef struct { - volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer - volatile uint32_t status; // error and done flags + volatile uint32_t _padding[8]; + volatile uint32_t status; volatile uint32_t hw_config; // see below volatile uint32_t dummy[3]; volatile uint32_t irqs; @@ -184,74 +182,6 @@ typedef struct { #define buffer_pool_status ((buffer_pool_status_t *) BUFFER_POOL_STATUS_BASE) -/* - * Buffer n's xfer is done. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_DONE(n) (0x00000001 << (n)) -#define BPS_DONE_0 BPS_DONE(0) -#define BPS_DONE_1 BPS_DONE(1) -#define BPS_DONE_2 BPS_DONE(2) -#define BPS_DONE_3 BPS_DONE(3) -#define BPS_DONE_4 BPS_DONE(4) -#define BPS_DONE_5 BPS_DONE(5) -#define BPS_DONE_6 BPS_DONE(6) -#define BPS_DONE_7 BPS_DONE(7) - -/* - * Buffer n's xfer had an error. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_ERROR(n) (0x00000100 << (n)) -#define BPS_ERROR_0 BPS_ERROR(0) -#define BPS_ERROR_1 BPS_ERROR(1) -#define BPS_ERROR_2 BPS_ERROR(2) -#define BPS_ERROR_3 BPS_ERROR(3) -#define BPS_ERROR_4 BPS_ERROR(4) -#define BPS_ERROR_5 BPS_ERROR(5) -#define BPS_ERROR_6 BPS_ERROR(6) -#define BPS_ERROR_7 BPS_ERROR(7) - -/* - * Buffer n is idle. A buffer is idle if it's not - * DONE, ERROR, or processing a transaction. If it's - * IDLE, it's safe to start a new transaction. - * - * Clear this bit by starting a xfer with - * bp_send_from_buf or bp_receive_to_buf. - */ -#define BPS_IDLE(n) (0x00010000 << (n)) -#define BPS_IDLE_0 BPS_IDLE(0) -#define BPS_IDLE_1 BPS_IDLE(1) -#define BPS_IDLE_2 BPS_IDLE(2) -#define BPS_IDLE_3 BPS_IDLE(3) -#define BPS_IDLE_4 BPS_IDLE(4) -#define BPS_IDLE_5 BPS_IDLE(5) -#define BPS_IDLE_6 BPS_IDLE(6) -#define BPS_IDLE_7 BPS_IDLE(7) - -/* - * Buffer n has a "slow path" packet in it. - * This bit is orthogonal to the bits above and indicates that - * the FPGA ethernet rx protocol engine has identified this packet - * as one requiring firmware intervention. - */ -#define BPS_SLOWPATH(n) (0x01000000 << (n)) -#define BPS_SLOWPATH_0 BPS_SLOWPATH(0) -#define BPS_SLOWPATH_1 BPS_SLOWPATH(1) -#define BPS_SLOWPATH_2 BPS_SLOWPATH(2) -#define BPS_SLOWPATH_3 BPS_SLOWPATH(3) -#define BPS_SLOWPATH_4 BPS_SLOWPATH(4) -#define BPS_SLOWPATH_5 BPS_SLOWPATH(5) -#define BPS_SLOWPATH_6 BPS_SLOWPATH(6) -#define BPS_SLOWPATH_7 BPS_SLOWPATH(7) - - -#define BPS_DONE_ALL 0x000000ff // mask of all dones -#define BPS_ERROR_ALL 0x0000ff00 // mask of all errors -#define BPS_IDLE_ALL 0x00ff0000 // mask of all idles -#define BPS_SLOWPATH_ALL 0xff000000 // mask of all slowpaths - // The hw_config register #define HWC_SIMULATION 0x80000000 @@ -316,49 +246,14 @@ hwconfig_wishbone_divisor(void) // --- buffer pool control regs --- typedef struct { - volatile uint32_t ctrl; + volatile uint32_t misc_ctrl; + volatile uint32_t ip_addr; + volatile uint32_t ctrl_ports; //ctrl (low 16) other (high 16) + volatile uint32_t data_ports; //dsp0 (low 16) dsp1 (high 16) + volatile uint32_t cpu_out_ctrl; + volatile uint32_t cpu_inp_ctrl; } buffer_pool_ctrl_t; -// buffer pool ports - -#define PORT_SERDES 0 // serial/deserializer -#define PORT_DSP 1 // DSP tx or rx pipeline -#define PORT_ETH 2 // ethernet tx or rx -#define PORT_RAM 3 // RAM tx or rx - -// the buffer pool ctrl register fields - -#define BPC_BUFFER(n) (((n) & 0xf) << 28) -#define BPC_BUFFER_MASK BPC_BUFFER(~0) -#define BPC_BUFFER_0 BPC_BUFFER(0) -#define BPC_BUFFER_1 BPC_BUFFER(1) -#define BPC_BUFFER_2 BPC_BUFFER(2) -#define BPC_BUFFER_3 BPC_BUFFER(3) -#define BPC_BUFFER_4 BPC_BUFFER(4) -#define BPC_BUFFER_5 BPC_BUFFER(5) -#define BPC_BUFFER_6 BPC_BUFFER(6) -#define BPC_BUFFER_7 BPC_BUFFER(7) -#define BPC_BUFFER_NIL BPC_BUFFER(0x8) // disable - -#define BPC_PORT(n) (((n) & 0x7) << 25) -#define BPC_PORT_MASK BPC_PORT(~0) -#define BPC_PORT_SERDES BPC_PORT(PORT_SERDES) -#define BPC_PORT_DSP BPC_PORT(PORT_DSP) -#define BPC_PORT_ETH BPC_PORT(PORT_ETH) -#define BPC_PORT_RAM BPC_PORT(PORT_RAM) -#define BPC_PORT_NIL BPC_PORT(0x4) // disable - -#define BPC_CLR (1 << 24) // mutually excl commands -#define BPC_READ (1 << 23) -#define BPC_WRITE (1 << 22) - -#define BPC_STEP(step) (((step) & 0xf) << 18) -#define BPC_STEP_MASK BPC_STEP(~0) -#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9) -#define BPC_LAST_LINE_MASK BPC_LAST_LINE(~0) -#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0) -#define BPC_FIRST_LINE_MASK BPC_FIRST_LINE(~0) - #define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE) // --- misc outputs --- diff --git a/firmware/microblaze/usrp2p/memory_map.h b/firmware/microblaze/usrp2p/memory_map.h index 3b2dc0057..5edb3b313 100644 --- a/firmware/microblaze/usrp2p/memory_map.h +++ b/firmware/microblaze/usrp2p/memory_map.h @@ -78,9 +78,7 @@ wb_1master #(.decode_w(8), #define BUFFER_POOL_RAM_BASE 0x4000 -#define NBUFFERS 8 #define BP_NLINES 0x0200 // number of 32-bit lines in a buffer -#define BP_LAST_LINE (BP_NLINES - 1) // last line in a buffer #define buffer_pool_ram \ ((uint32_t *) BUFFER_POOL_RAM_BASE) @@ -198,8 +196,8 @@ typedef struct { #define BUFFER_POOL_STATUS_BASE 0x3300 typedef struct { - volatile uint32_t last_line[NBUFFERS]; // last line xfer'd in buffer - volatile uint32_t status; // error and done flags + volatile uint32_t _padding[8]; + volatile uint32_t status; volatile uint32_t hw_config; // see below volatile uint32_t dummy[3]; volatile uint32_t irqs; @@ -211,74 +209,6 @@ typedef struct { #define BUTTON_PUSHED ((buffer_pool_status->irqs & PIC_BUTTON) ? 0 : 1) -/* - * Buffer n's xfer is done. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_DONE(n) (0x00000001 << (n)) -#define BPS_DONE_0 BPS_DONE(0) -#define BPS_DONE_1 BPS_DONE(1) -#define BPS_DONE_2 BPS_DONE(2) -#define BPS_DONE_3 BPS_DONE(3) -#define BPS_DONE_4 BPS_DONE(4) -#define BPS_DONE_5 BPS_DONE(5) -#define BPS_DONE_6 BPS_DONE(6) -#define BPS_DONE_7 BPS_DONE(7) - -/* - * Buffer n's xfer had an error. - * Clear this bit by issuing bp_clear_buf(n) - */ -#define BPS_ERROR(n) (0x00000100 << (n)) -#define BPS_ERROR_0 BPS_ERROR(0) -#define BPS_ERROR_1 BPS_ERROR(1) -#define BPS_ERROR_2 BPS_ERROR(2) -#define BPS_ERROR_3 BPS_ERROR(3) -#define BPS_ERROR_4 BPS_ERROR(4) -#define BPS_ERROR_5 BPS_ERROR(5) -#define BPS_ERROR_6 BPS_ERROR(6) -#define BPS_ERROR_7 BPS_ERROR(7) - -/* - * Buffer n is idle. A buffer is idle if it's not - * DONE, ERROR, or processing a transaction. If it's - * IDLE, it's safe to start a new transaction. - * - * Clear this bit by starting a xfer with - * bp_send_from_buf or bp_receive_to_buf. - */ -#define BPS_IDLE(n) (0x00010000 << (n)) -#define BPS_IDLE_0 BPS_IDLE(0) -#define BPS_IDLE_1 BPS_IDLE(1) -#define BPS_IDLE_2 BPS_IDLE(2) -#define BPS_IDLE_3 BPS_IDLE(3) -#define BPS_IDLE_4 BPS_IDLE(4) -#define BPS_IDLE_5 BPS_IDLE(5) -#define BPS_IDLE_6 BPS_IDLE(6) -#define BPS_IDLE_7 BPS_IDLE(7) - -/* - * Buffer n has a "slow path" packet in it. - * This bit is orthogonal to the bits above and indicates that - * the FPGA ethernet rx protocol engine has identified this packet - * as one requiring firmware intervention. - */ -#define BPS_SLOWPATH(n) (0x01000000 << (n)) -#define BPS_SLOWPATH_0 BPS_SLOWPATH(0) -#define BPS_SLOWPATH_1 BPS_SLOWPATH(1) -#define BPS_SLOWPATH_2 BPS_SLOWPATH(2) -#define BPS_SLOWPATH_3 BPS_SLOWPATH(3) -#define BPS_SLOWPATH_4 BPS_SLOWPATH(4) -#define BPS_SLOWPATH_5 BPS_SLOWPATH(5) -#define BPS_SLOWPATH_6 BPS_SLOWPATH(6) -#define BPS_SLOWPATH_7 BPS_SLOWPATH(7) - - -#define BPS_DONE_ALL 0x000000ff // mask of all dones -#define BPS_ERROR_ALL 0x0000ff00 // mask of all errors -#define BPS_IDLE_ALL 0x00ff0000 // mask of all idles -#define BPS_SLOWPATH_ALL 0xff000000 // mask of all slowpaths - // The hw_config register #define HWC_SIMULATION 0x80000000 @@ -343,49 +273,14 @@ hwconfig_wishbone_divisor(void) // --- buffer pool control regs --- typedef struct { - volatile uint32_t ctrl; + volatile uint32_t misc_ctrl; + volatile uint32_t ip_addr; + volatile uint32_t ctrl_ports; //ctrl (low 16) other (high 16) + volatile uint32_t data_ports; //dsp0 (low 16) dsp1 (high 16) + volatile uint32_t cpu_out_ctrl; + volatile uint32_t cpu_inp_ctrl; } buffer_pool_ctrl_t; -// buffer pool ports - -#define PORT_SERDES 0 // serial/deserializer -#define PORT_DSP 1 // DSP tx or rx pipeline -#define PORT_ETH 2 // ethernet tx or rx -#define PORT_RAM 3 // RAM tx or rx - -// the buffer pool ctrl register fields - -#define BPC_BUFFER(n) (((n) & 0xf) << 28) -#define BPC_BUFFER_MASK BPC_BUFFER(~0) -#define BPC_BUFFER_0 BPC_BUFFER(0) -#define BPC_BUFFER_1 BPC_BUFFER(1) -#define BPC_BUFFER_2 BPC_BUFFER(2) -#define BPC_BUFFER_3 BPC_BUFFER(3) -#define BPC_BUFFER_4 BPC_BUFFER(4) -#define BPC_BUFFER_5 BPC_BUFFER(5) -#define BPC_BUFFER_6 BPC_BUFFER(6) -#define BPC_BUFFER_7 BPC_BUFFER(7) -#define BPC_BUFFER_NIL BPC_BUFFER(0x8) // disable - -#define BPC_PORT(n) (((n) & 0x7) << 25) -#define BPC_PORT_MASK BPC_PORT(~0) -#define BPC_PORT_SERDES BPC_PORT(PORT_SERDES) -#define BPC_PORT_DSP BPC_PORT(PORT_DSP) -#define BPC_PORT_ETH BPC_PORT(PORT_ETH) -#define BPC_PORT_RAM BPC_PORT(PORT_RAM) -#define BPC_PORT_NIL BPC_PORT(0x4) // disable - -#define BPC_CLR (1 << 24) // mutually excl commands -#define BPC_READ (1 << 23) -#define BPC_WRITE (1 << 22) - -#define BPC_STEP(step) (((step) & 0xf) << 18) -#define BPC_STEP_MASK BPC_STEP(~0) -#define BPC_LAST_LINE(line) (((line) & 0x1ff) << 9) -#define BPC_LAST_LINE_MASK BPC_LAST_LINE(~0) -#define BPC_FIRST_LINE(line) (((line) & 0x1ff) << 0) -#define BPC_FIRST_LINE_MASK BPC_FIRST_LINE(~0) - #define buffer_pool_ctrl ((buffer_pool_ctrl_t *) BUFFER_POOL_CTRL_BASE) // --- misc outputs --- diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst index 8e5743102..3031a0075 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -101,7 +101,7 @@ On some systems, the firewall will block UDP broadcast packets. It is recommended that you change or disable your firewall settings. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Multiple device configuration +Multiple devices per host ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For maximum throughput, one ethernet interface per USRP2 is recommended, although multiple devices may be connected via a gigabit ethernet switch. @@ -210,6 +210,66 @@ Example device address string representation for 2 USRP2s with IPv4 addresses 19 addr0=192.168.10.2, addr1=192.168.20.2 ------------------------------------------------------------------------ +Using the MIMO Cable +------------------------------------------------------------------------ +The MIMO cable allows two USRP devices to share reference clocks, +time synchronization, and the ethernet interface. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Shared ethernet mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In shared ethernet mode, +only one device in the configuration can be attached to the ethernet. +This device will be referred to as the master, and the other device, the slave. + +* The master provides reference clock and time synchronization to the slave. +* All data passing between the host and the slave is routed over the MIMO cable. +* Both master and slave must have different IPv4 addresses in the same subnet. +* The master and slave may be used individually or in a multi-device configuration. +* External clocking is optional, and should only be supplied to the master device. +* The role of slave and master may be switched with the "mimo_mode" device address (see dual ethernet mode). + +Example device address string representation for 2 USRP2s with IPv4 addresses 192.168.10.2 (master) and 192.168.10.3 (slave) +:: + + -- Multi-device example -- + + addr0=192.168.10.2, addr1=192.168.10.3 + + -- Two single devices example -- + + addr=192.168.10.2 + + addr=192.168.10.3 + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Dual ethernet mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In dual ethernet mode, +both devices in the configuration must be attached to the ethernet. +One of the devices in the configuration will be configured to provide synchronization. +This device will be referred to as the master, and the other device, the slave. + +* The master provides reference clock and time synchronization to the slave. +* The devices require the special device address argument "mimo_mode" set. +* Both master and slave must have different IPv4 addresses in different subnets. +* The master and slave may be used individually or in a multi-device configuration. +* External clocking is optional, and should only be supplied to the master device. + +Example device address string representation for 2 USRP2s with IPv4 addresses 192.168.10.2 (master) and 192.168.20.2 (slave) +:: + + -- Multi-device example -- + + addr0=192.168.10.2, mimo_mode0=master, addr1=192.168.20.2, mimo_mode1=slave + + -- Two single devices example -- + + addr=192.168.10.2, mimo_mode=master + + addr=192.168.20.2, mimo_mode=slave + +------------------------------------------------------------------------ Hardware setup notes ------------------------------------------------------------------------ @@ -220,7 +280,7 @@ The LEDs on the front panel can be useful in debugging hardware and software iss The LEDs reveal the following about the state of the device: * **LED A:** transmitting -* **LED B:** serdes link +* **LED B:** mimo cable link * **LED C:** receiving * **LED D:** firmware loaded * **LED E:** reference lock diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 9342fbb7b..5966dcf3a 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -32,12 +32,10 @@ namespace uhd{ REF_AUTO = 'a', //automatic (device specific) REF_INT = 'i', //internal reference REF_SMA = 's', //external sma port - REF_MIMO = 'm' //mimo cable (usrp2 only) } ref_source; enum pps_source_t { PPS_INT = 'i', //there is no internal PPS_SMA = 's', //external sma port - PPS_MIMO = 'm' //mimo cable (usrp2 only) } pps_source; enum pps_polarity_t { PPS_NEG = 'n', //negative edge diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index afd69cae9..81b73fcc2 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -36,8 +36,6 @@ IF(ENABLE_USRP2) ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.cpp - ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.cpp diff --git a/host/lib/usrp/usrp2/clock_ctrl.cpp b/host/lib/usrp/usrp2/clock_ctrl.cpp index 428d5539b..27ccefb2b 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.cpp +++ b/host/lib/usrp/usrp2/clock_ctrl.cpp @@ -22,10 +22,13 @@ #include <uhd/utils/assert.hpp> #include <boost/cstdint.hpp> #include <boost/lexical_cast.hpp> +#include <boost/math/special_functions/round.hpp> #include <iostream> using namespace uhd; +static const bool enb_test_clk = false; + /*! * A usrp2 clock control specific to the ad9510 ic. */ @@ -66,13 +69,12 @@ public: this->enable_external_ref(false); this->enable_rx_dboard_clock(false); this->enable_tx_dboard_clock(false); + this->enable_mimo_clock_out(false); /* private clock enables, must be set here */ this->enable_dac_clock(true); this->enable_adc_clock(true); - - /* always driving the mimo reference */ - this->enable_mimo_clock_out(true); + this->enable_test_clock(enb_test_clk); } ~usrp2_clock_ctrl_impl(void){ @@ -83,6 +85,7 @@ public: this->enable_dac_clock(false); this->enable_adc_clock(false); this->enable_mimo_clock_out(false); + this->enable_test_clock(false); } void enable_mimo_clock_out(bool enb){ @@ -246,6 +249,54 @@ public: double get_master_clock_rate(void){ return 100e6; } + + void set_mimo_clock_delay(double delay) { + //delay_val is a 5-bit value (0-31) for fine control + //the equations below determine delay for a given ramp current, # of caps and fine delay register + //delay range: + //range_ns = 200*((caps+3)/i_ramp_ua)*1.3286 + //offset (zero delay): + //offset_ns = 0.34 + (1600 - i_ramp_ua)*1e-4 + ((caps-1)/ramp)*6 + //delay_ns = offset_ns + range_ns * delay / 31 + + int delay_val = boost::math::iround(delay/9.744e-9*31); + + if(delay_val == 0) { + switch(clk_regs.exp) { + case 5: + _ad9510_regs.delay_control_out5 = 1; + break; + case 6: + _ad9510_regs.delay_control_out6 = 1; + break; + default: + break; //delay not supported on U2 rev 3 + } + } else { + switch(clk_regs.exp) { + case 5: + _ad9510_regs.delay_control_out5 = 0; + _ad9510_regs.ramp_current_out5 = ad9510_regs_t::RAMP_CURRENT_OUT5_200UA; + _ad9510_regs.ramp_capacitor_out5 = ad9510_regs_t::RAMP_CAPACITOR_OUT5_4CAPS; + _ad9510_regs.delay_fine_adjust_out5 = delay_val; + this->write_reg(0x34); + this->write_reg(0x35); + this->write_reg(0x36); + break; + case 6: + _ad9510_regs.delay_control_out6 = 0; + _ad9510_regs.ramp_current_out6 = ad9510_regs_t::RAMP_CURRENT_OUT6_200UA; + _ad9510_regs.ramp_capacitor_out6 = ad9510_regs_t::RAMP_CAPACITOR_OUT6_4CAPS; + _ad9510_regs.delay_fine_adjust_out6 = delay_val; + this->write_reg(0x38); + this->write_reg(0x39); + this->write_reg(0x3A); + break; + default: + break; + } + } + } private: /*! diff --git a/host/lib/usrp/usrp2/clock_ctrl.hpp b/host/lib/usrp/usrp2/clock_ctrl.hpp index db6c52c83..9ccbc959e 100644 --- a/host/lib/usrp/usrp2/clock_ctrl.hpp +++ b/host/lib/usrp/usrp2/clock_ctrl.hpp @@ -91,8 +91,18 @@ public: virtual void enable_test_clock(bool enb) = 0; /*! - * TODO other clock control api here.... + * Enable/disable the ref clock output over the serdes cable. + * \param enb true to enable + */ + virtual void enable_mimo_clock_out(bool enb) = 0; + + /*! + * Set the output delay of the mimo clock + * Used to synchronise daisy-chained USRPs over the MIMO cable + * Can also be used to adjust delay for uneven reference cable lengths + * \param delay the clock delay in seconds */ + virtual void set_mimo_clock_delay(double delay) = 0; }; diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index a9c39e650..efbb4b954 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -33,8 +33,8 @@ extern "C" { #endif //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 3 -#define USRP2_FW_COMPAT_NUM 7 +#define USRP2_FPGA_COMPAT_NUM 4 +#define USRP2_FW_COMPAT_NUM 8 //used to differentiate control packets over data port #define USRP2_INVALID_VRT_HEADER 0 diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 766ea993c..b8ebd6030 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -27,6 +27,10 @@ #include <iostream> #include <boost/date_time/posix_time/posix_time.hpp> +static const double mimo_clock_delay_usrp2_rev4 = 4.18e-9; +static const double mimo_clock_delay_usrp_n2xx = 0; //TODO +static const int mimo_clock_sync_delay_cycles = 134; + using namespace uhd; using namespace uhd::usrp; using namespace boost::posix_time; @@ -38,8 +42,8 @@ usrp2_mboard_impl::usrp2_mboard_impl( size_t index, transport::udp_simple::sptr ctrl_transport, transport::zero_copy_if::sptr data_transport, - size_t recv_samps_per_packet, - const device_addr_t &flow_control_hints + const device_addr_t &device_args, + size_t recv_samps_per_packet ): _index(index), _iface(usrp2_iface::make(ctrl_transport)) @@ -58,7 +62,6 @@ usrp2_mboard_impl::usrp2_mboard_impl( //contruct the interfaces to mboard perifs _clock_ctrl = usrp2_clock_ctrl::make(_iface); _codec_ctrl = usrp2_codec_ctrl::make(_iface); - _serdes_ctrl = usrp2_serdes_ctrl::make(_iface); //_gps_ctrl = usrp2_gps_ctrl::make(_iface); //if(_gps_ctrl->gps_detected()) std::cout << "GPS time: " << _gps_ctrl->get_time() << std::endl; @@ -98,14 +101,14 @@ usrp2_mboard_impl::usrp2_mboard_impl( _iface->poke32(_iface->regs.tx_ctrl_policy, U2_FLAG_TX_CTRL_POLICY_NEXT_PACKET); //setting the cycles per update (disabled by default) - const double ups_per_sec = flow_control_hints.cast<double>("ups_per_sec", 0.0); + const double ups_per_sec = device_args.cast<double>("ups_per_sec", 0.0); if (ups_per_sec > 0.0){ const size_t cycles_per_up = size_t(_clock_ctrl->get_master_clock_rate()/ups_per_sec); _iface->poke32(_iface->regs.tx_ctrl_cycles_per_up, U2_FLAG_TX_CTRL_UP_ENB | cycles_per_up); } //setting the packets per update (enabled by default) - const double ups_per_fifo = flow_control_hints.cast<double>("ups_per_fifo", 8.0); + const double ups_per_fifo = device_args.cast<double>("ups_per_fifo", 8.0); if (ups_per_fifo > 0.0){ const size_t packets_per_up = size_t(usrp2_impl::sram_bytes/ups_per_fifo/data_transport->get_send_frame_size()); _iface->poke32(_iface->regs.tx_ctrl_packets_per_up, U2_FLAG_TX_CTRL_UP_ENB | packets_per_up); @@ -118,6 +121,20 @@ usrp2_mboard_impl::usrp2_mboard_impl( init_duc_config(); //initialize the clock configuration + if (device_args.has_key("mimo_mode")){ + if (device_args["mimo_mode"] == "master"){ + _mimo_clocking_mode_is_master = true; + } + else if (device_args["mimo_mode"] == "slave"){ + _mimo_clocking_mode_is_master = false; + } + else throw std::runtime_error( + "mimo_mode must be set to master or slave" + ); + } + else { + _mimo_clocking_mode_is_master = bool(_iface->peek32(_iface->regs.status) & (1 << 8)); + } init_clock_config(); //init the codec before the dboard @@ -155,7 +172,6 @@ void usrp2_mboard_impl::update_clock_config(void){ //translate pps source enums switch(_clock_config.pps_source){ case clock_config_t::PPS_SMA: pps_flags |= U2_FLAG_TIME64_PPS_SMA; break; - case clock_config_t::PPS_MIMO: pps_flags |= U2_FLAG_TIME64_PPS_MIMO; break; default: throw std::runtime_error("unhandled clock configuration pps source"); } @@ -176,7 +192,6 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x12); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; - case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; default: throw std::runtime_error("unhandled clock configuration reference source"); } _clock_ctrl->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO @@ -187,7 +202,6 @@ void usrp2_mboard_impl::update_clock_config(void){ switch(_clock_config.ref_source){ case clock_config_t::REF_INT : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x10); break; case clock_config_t::REF_SMA : _iface->poke32(_iface->regs.misc_ctrl_clock, 0x1C); break; - case clock_config_t::REF_MIMO: _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); break; default: throw std::runtime_error("unhandled clock configuration reference source"); } _clock_ctrl->enable_external_ref(_clock_config.ref_source != clock_config_t::REF_INT); @@ -195,6 +209,36 @@ void usrp2_mboard_impl::update_clock_config(void){ case usrp2_iface::USRP_NXXX: break; } + + //Handle the serdes clocking based on master/slave mode: + // - Masters always drive the clock over serdes. + // - Slaves always lock to this serdes clock. + // - Slaves lock their time over the serdes. + if (_mimo_clocking_mode_is_master){ + _clock_ctrl->enable_mimo_clock_out(true); + switch(_iface->get_rev()){ + case usrp2_iface::USRP_N200: + case usrp2_iface::USRP_N210: + _clock_ctrl->set_mimo_clock_delay(mimo_clock_delay_usrp_n2xx); + break; + + case usrp2_iface::USRP2_REV4: + _clock_ctrl->set_mimo_clock_delay(mimo_clock_delay_usrp2_rev4); + break; + + default: break; //not handled + } + _iface->poke32(_iface->regs.time64_mimo_sync, 0); + } + else{ + _iface->poke32(_iface->regs.misc_ctrl_clock, 0x15); + _clock_ctrl->enable_external_ref(true); + _clock_ctrl->enable_mimo_clock_out(false); + _iface->poke32(_iface->regs.time64_mimo_sync, + (1 << 8) | (mimo_clock_sync_delay_cycles & 0xff) + ); + } + } void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){ diff --git a/host/lib/usrp/usrp2/serdes_ctrl.cpp b/host/lib/usrp/usrp2/serdes_ctrl.cpp deleted file mode 100644 index 1cda22f45..000000000 --- a/host/lib/usrp/usrp2/serdes_ctrl.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// - -#include "serdes_ctrl.hpp" -#include "usrp2_regs.hpp" - -using namespace uhd; - -/*! - * A usrp2 serdes control implementation - */ -class usrp2_serdes_ctrl_impl : public usrp2_serdes_ctrl{ -public: - usrp2_serdes_ctrl_impl(usrp2_iface::sptr iface){ - _iface = iface; - _iface->poke32(_iface->regs.misc_ctrl_serdes, U2_FLAG_MISC_CTRL_SERDES_ENABLE | U2_FLAG_MISC_CTRL_SERDES_RXEN); - } - - ~usrp2_serdes_ctrl_impl(void){ - _iface->poke32(_iface->regs.misc_ctrl_serdes, 0); //power-down - } - -private: - usrp2_iface::sptr _iface; -}; - -/*********************************************************************** - * Public make function for the usrp2 serdes control - **********************************************************************/ -usrp2_serdes_ctrl::sptr usrp2_serdes_ctrl::make(usrp2_iface::sptr iface){ - return sptr(new usrp2_serdes_ctrl_impl(iface)); -} diff --git a/host/lib/usrp/usrp2/serdes_ctrl.hpp b/host/lib/usrp/usrp2/serdes_ctrl.hpp deleted file mode 100644 index 3c909c531..000000000 --- a/host/lib/usrp/usrp2/serdes_ctrl.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// - -#ifndef INCLUDED_SERDES_CTRL_HPP -#define INCLUDED_SERDES_CTRL_HPP - -#include "usrp2_iface.hpp" -#include <boost/shared_ptr.hpp> -#include <boost/utility.hpp> - -class usrp2_serdes_ctrl : boost::noncopyable{ -public: - typedef boost::shared_ptr<usrp2_serdes_ctrl> sptr; - - /*! - * Make a serdes control object for the usrp2 serdes port. - * \param _iface a pointer to the usrp2 interface object - * \return a new serdes control object - */ - static sptr make(usrp2_iface::sptr iface); - - //TODO fill me in with virtual methods - -}; - -#endif /* INCLUDED_SERDES_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index c3bbe4d65..133c39a35 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -201,8 +201,9 @@ sep_indexed_dev_addrs(device_addr); //create a ctrl and data transport for each address std::vector<udp_simple::sptr> ctrl_transports; std::vector<zero_copy_if::sptr> data_transports; + const device_addrs_t device_addrs = sep_indexed_dev_addrs(device_addr); - BOOST_FOREACH(const device_addr_t &dev_addr_i, sep_indexed_dev_addrs(device_addr)){ + BOOST_FOREACH(const device_addr_t &dev_addr_i, device_addrs){ ctrl_transports.push_back(udp_simple::make_connected( dev_addr_i["addr"], num2str(USRP2_UDP_CTRL_PORT) )); @@ -213,7 +214,7 @@ sep_indexed_dev_addrs(device_addr); //create the usrp2 implementation guts return device::sptr( - new usrp2_impl(ctrl_transports, data_transports, device_addr) + new usrp2_impl(ctrl_transports, data_transports, device_addrs) ); } @@ -227,7 +228,7 @@ UHD_STATIC_BLOCK(register_usrp2_device){ usrp2_impl::usrp2_impl( std::vector<udp_simple::sptr> ctrl_transports, std::vector<zero_copy_if::sptr> data_transports, - const device_addr_t &flow_control_hints + const device_addrs_t &device_args ): _data_transports(data_transports) { @@ -244,11 +245,10 @@ usrp2_impl::usrp2_impl( //!!!!! set the otw type here before continuing, its used below //create a new mboard handler for each control transport - for(size_t i = 0; i < ctrl_transports.size(); i++){ + for(size_t i = 0; i < device_args.size(); i++){ _mboards.push_back(usrp2_mboard_impl::sptr(new usrp2_mboard_impl( - i, ctrl_transports[i], data_transports[i], - this->get_max_recv_samps_per_packet(), - flow_control_hints + i, ctrl_transports[i], data_transports[i], device_args[i], + this->get_max_recv_samps_per_packet() ))); //use an empty name when there is only one mboard std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : ""; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index aa8eb0155..85c00b079 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -22,7 +22,6 @@ #include "clock_ctrl.hpp" #include "codec_ctrl.hpp" #include "gps_ctrl.hpp" -#include "serdes_ctrl.hpp" #include <uhd/device.hpp> #include <uhd/utils/pimpl.hpp> #include <uhd/types/dict.hpp> @@ -86,8 +85,8 @@ public: size_t index, uhd::transport::udp_simple::sptr, uhd::transport::zero_copy_if::sptr, - size_t recv_samps_per_packet, - const uhd::device_addr_t &flow_control_hints + const uhd::device_addr_t &device_args, + size_t recv_samps_per_packet ); ~usrp2_mboard_impl(void); @@ -100,12 +99,12 @@ public: private: size_t _index; bool _continuous_streaming; + bool _mimo_clocking_mode_is_master; //interfaces usrp2_iface::sptr _iface; usrp2_clock_ctrl::sptr _clock_ctrl; usrp2_codec_ctrl::sptr _codec_ctrl; - usrp2_serdes_ctrl::sptr _serdes_ctrl; usrp2_gps_ctrl::sptr _gps_ctrl; //properties for this mboard @@ -192,7 +191,7 @@ public: usrp2_impl( std::vector<uhd::transport::udp_simple::sptr> ctrl_transports, std::vector<uhd::transport::zero_copy_if::sptr> data_transports, - const uhd::device_addr_t &flow_control_hints + const uhd::device_addrs_t &device_args ); ~usrp2_impl(void); diff --git a/host/lib/usrp/usrp2/usrp2_regs.cpp b/host/lib/usrp/usrp2/usrp2_regs.cpp index dd0433816..82ad30f08 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.cpp +++ b/host/lib/usrp/usrp2/usrp2_regs.cpp @@ -57,6 +57,8 @@ usrp2_regs_t usrp2_get_regs(bool use_n2xx_map) { x.time64_flags = sr_addr(misc_output_base, x.sr_time64 + 2); x.time64_imm = sr_addr(misc_output_base, x.sr_time64 + 3); x.time64_tps = sr_addr(misc_output_base, x.sr_time64 + 4); + x.time64_mimo_sync = sr_addr(misc_output_base, x.sr_time64 + 5); + x.status = bp_base + 4*8; x.time64_secs_rb = bp_base + 4*10; x.time64_ticks_rb = bp_base + 4*11; x.compat_num_rb = bp_base + 4*12; diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 9936d634a..0311ac625 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -57,6 +57,8 @@ typedef struct { int time64_flags; // flags -- see chart below int time64_imm; // set immediate (0=latch on next pps, 1=latch immediate, default=0) int time64_tps; // ticks per second rollover count + int time64_mimo_sync; + int status; int time64_secs_rb; int time64_ticks_rb; int compat_num_rb; |