diff options
Diffstat (limited to 'usrp2/firmware')
-rw-r--r-- | usrp2/firmware/apps/app_common_v2.c | 123 | ||||
-rw-r--r-- | usrp2/firmware/include/usrp2_eth_packet.h | 42 | ||||
-rw-r--r-- | usrp2/firmware/lib/memory_map.h | 25 | ||||
-rw-r--r-- | usrp2/firmware/lib/u2_init.c | 4 |
4 files changed, 153 insertions, 41 deletions
diff --git a/usrp2/firmware/apps/app_common_v2.c b/usrp2/firmware/apps/app_common_v2.c index 60fa63ee3..6d9606d45 100644 --- a/usrp2/firmware/apps/app_common_v2.c +++ b/usrp2/firmware/apps/app_common_v2.c @@ -40,17 +40,11 @@ dbsm_t *ac_could_be_sending_to_eth; static unsigned char exp_seqno __attribute__((unused)) = 0; -static bool -burn_mac_addr(const op_burn_mac_addr_t *p) -{ - return ethernet_set_mac_addr(&p->addr); -} - -static bool +static inline bool sync_to_pps(const op_generic_t *p) { timesync_regs->sync_on_next_pps = 1; - putstr("SYNC to PPS\n"); + //putstr("SYNC to PPS\n"); return true; } @@ -65,7 +59,7 @@ sync_every_pps(const op_generic_t *p) return true; } -static bool +static inline bool config_mimo_cmd(const op_config_mimo_t *p) { clocks_mimo_config(p->flags); @@ -348,8 +342,8 @@ peek_cmd(const op_peek_t *p, { op_generic_t *r = (op_generic_t *) reply_payload; - putstr("peek: addr="); puthex32(p->addr); - printf(" bytes=%u\n", p->bytes); + //putstr("peek: addr="); puthex32(p->addr); + //printf(" bytes=%u\n", p->bytes); if ((reply_payload_space < (sizeof(*r) + p->bytes)) || p->bytes > MAX_SUBPKT_LEN - sizeof(op_generic_t)) { @@ -371,8 +365,8 @@ static bool poke_cmd(const op_poke_t *p) { int bytes = p->len - sizeof(*p); - putstr("poke: addr="); puthex32(p->addr); - printf(" bytes=%u\n", bytes); + //putstr("poke: addr="); puthex32(p->addr); + //printf(" bytes=%u\n", bytes); uint8_t *src = (uint8_t *)p + sizeof(*p); memcpy_wa((void *)p->addr, src, bytes); @@ -391,6 +385,26 @@ set_lo_offset_cmd(const op_freq_t *p) } static size_t +gpio_read_cmd(const op_gpio_t *p, + void *reply_payload, size_t reply_payload_space) +{ + op_gpio_read_reply_t *r = (op_gpio_read_reply_t *) reply_payload; + if (reply_payload_space < sizeof(*r)) // no room + return 0; + + // Build reply subpacket + + r->opcode = OP_GPIO_READ_REPLY; + r->len = sizeof(op_gpio_read_reply_t); + r->rid = p->rid; + r->ok = true; + r->mbz = 0; + r->value = hal_gpio_read(p->bank); + + return r->len; +} + +static size_t generic_reply(const op_generic_t *p, void *reply_payload, size_t reply_payload_space, bool ok) @@ -438,6 +452,7 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len) int payload_len = len - sizeof(u2_eth_packet_t); size_t subpktlen = 0; + bool ok = false; while (payload_len >= sizeof(op_generic_t)){ const op_generic_t *gp = (const op_generic_t *) payload; @@ -454,34 +469,30 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len) break; case OP_CONFIG_TX_V2: - subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload, - reply_payload, reply_payload_space); + subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload, reply_payload, reply_payload_space); break; case OP_CONFIG_RX_V2: - subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload, - reply_payload, reply_payload_space); + subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload, reply_payload, reply_payload_space); break; case OP_START_RX_STREAMING: start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload); - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true); - break; + ok = true; + goto generic_reply; case OP_STOP_RX: stop_rx_cmd(); - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true); - break; + ok = true; + goto generic_reply; case OP_BURN_MAC_ADDR: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - burn_mac_addr((op_burn_mac_addr_t *) payload)); - break; + ok = ethernet_set_mac_addr(&((op_burn_mac_addr_t *)payload)->addr); + goto generic_reply; case OP_CONFIG_MIMO: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - config_mimo_cmd((op_config_mimo_t *) payload)); - break; + ok = config_mimo_cmd((op_config_mimo_t *) payload); + goto generic_reply; case OP_READ_TIME: subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space); @@ -492,33 +503,65 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len) break; case OP_SYNC_TO_PPS: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - sync_to_pps((op_generic_t *) payload)); - break; + sync_to_pps((op_generic_t *) payload); + ok = true; + goto generic_reply; case OP_PEEK: subpktlen = peek_cmd((op_peek_t *)payload, reply_payload, reply_payload_space); break; case OP_POKE: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - poke_cmd((op_poke_t *)payload)); - break; + ok = poke_cmd((op_poke_t *)payload); + goto generic_reply; case OP_SET_TX_LO_OFFSET: case OP_SET_RX_LO_OFFSET: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - set_lo_offset_cmd((op_freq_t *)payload)); - break; + ok = set_lo_offset_cmd((op_freq_t *)payload); + goto generic_reply; case OP_RESET_DB: db_init(); - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true); - break; + ok = true; + goto generic_reply; case OP_SYNC_EVERY_PPS: - subpktlen = generic_reply(gp, reply_payload, reply_payload_space, - sync_every_pps((op_generic_t *) payload)); + ok = sync_every_pps((op_generic_t *) payload); + goto generic_reply; + + case OP_GPIO_SET_DDR: + ok = true; + hal_gpio_set_ddr(((op_gpio_t *)payload)->bank, + ((op_gpio_t *)payload)->value, + ((op_gpio_t *)payload)->mask); + goto generic_reply; + + case OP_GPIO_SET_SELS: + ok = true; + hal_gpio_set_sels(((op_gpio_set_sels_t *)payload)->bank, + (char *)(&((op_gpio_set_sels_t *)payload)->sels)); + goto generic_reply; + + case OP_GPIO_READ: + subpktlen = gpio_read_cmd((op_gpio_t *) payload, reply_payload, reply_payload_space); + break; + + case OP_GPIO_WRITE: + ok = true; + hal_gpio_write(((op_gpio_t *)payload)->bank, + ((op_gpio_t *)payload)->value, + ((op_gpio_t *)payload)->mask); + goto generic_reply; + + case OP_GPIO_STREAM: + ok = true; + dsp_rx_regs->gpio_stream_enable = (uint32_t)((op_gpio_t *)payload)->value; + goto generic_reply; + + // Add new opcode handlers here + + generic_reply: + subpktlen = generic_reply(gp, reply_payload, reply_payload_space, ok); break; default: diff --git a/usrp2/firmware/include/usrp2_eth_packet.h b/usrp2/firmware/include/usrp2_eth_packet.h index a118c1b55..b0123c584 100644 --- a/usrp2/firmware/include/usrp2_eth_packet.h +++ b/usrp2/firmware/include/usrp2_eth_packet.h @@ -198,6 +198,16 @@ typedef struct { #define OP_RESET_DB_REPLY (OP_RESET_DB | OP_REPLY_BIT) #define OP_SYNC_EVERY_PPS 16 #define OP_SYNC_EVERY_PPS_REPLY (OP_SYNC_EVERY_PPS | OP_REPLY_BIT) +#define OP_GPIO_SET_DDR 17 +#define OP_GPIO_SET_DDR_REPLY (OP_GPIO_SET_DDR | OP_REPLY_BIT) +#define OP_GPIO_SET_SELS 18 +#define OP_GPIO_SET_SELS_REPLY (OP_GPIO_SET_SELS | OP_REPLY_BIT) +#define OP_GPIO_READ 19 +#define OP_GPIO_READ_REPLY (OP_GPIO_READ | OP_REPLY_BIT) +#define OP_GPIO_WRITE 20 +#define OP_GPIO_WRITE_REPLY (OP_GPIO_WRITE | OP_REPLY_BIT) +#define OP_GPIO_STREAM 21 +#define OP_GPIO_STREAM_REPLY (OP_GPIO_STREAM | OP_REPLY_BIT) /* * All subpackets are a multiple of 4 bytes long. @@ -425,6 +435,35 @@ typedef struct { } _AL4 op_freq_t; /* + * Structures for commands in GPIO system + */ +typedef struct { + uint8_t opcode; // OP_GPIO_SET_DDR, OP_GPIO_WRITE, OP_GPIO_STREAM + uint8_t len; + uint8_t rid; + uint8_t bank; + uint16_t value; + uint16_t mask; +} _AL4 op_gpio_t; + +typedef struct { + uint8_t opcode; // OP_GPIO_SET_SELS + uint8_t len; + uint8_t rid; + uint8_t bank; + uint8_t sels[16]; +} _AL4 op_gpio_set_sels_t; + +typedef struct { + uint8_t opcode; // OP_GPIO_READ_REPLY + uint8_t len; + uint8_t rid; + uint8_t ok; + uint16_t mbz; + uint16_t value; +} _AL4 op_gpio_read_reply_t; + +/* * ================================================================ * union of all of subpacket types * ================================================================ @@ -444,6 +483,9 @@ typedef union { op_peek_t op_peek; op_poke_t op_poke; op_freq_t op_freq; + op_gpio_t op_gpio; + op_gpio_set_sels_t op_gpio_set_sels; + op_gpio_read_reply_t op_gpio_read_reply; } u2_subpkt_t; diff --git a/usrp2/firmware/lib/memory_map.h b/usrp2/firmware/lib/memory_map.h index fb6fc45d7..78a4330d2 100644 --- a/usrp2/firmware/lib/memory_map.h +++ b/usrp2/firmware/lib/memory_map.h @@ -471,6 +471,31 @@ typedef struct { */ volatile uint32_t rx_mux; // called adc_mux in dsp_core_rx.v + /*! + * \brief Streaming GPIO configuration + * + * This determines whether the LSBs of I and Q samples come from the DSP + * pipeline or from the io_rx GPIO pins. To stream GPIO, one must first + * set the GPIO data direction register to have io_rx[15] and/or io_rx[14] + * configured as inputs. The GPIO pins will be sampled at the time the + * remainder of the DSP sample is strobed into the RX sample FIFO. There + * will be a decimation-dependent fixed time offset between the GPIO + * sample stream and the associated RF samples. + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * | MBZ |Q|I| + * +-------+-------+-------+-------+-------+-------+-------+-------+ + * + * I 0=LSB comes from DSP pipeline (default) + * 1=LSB comes from io_rx[15] + * + * Q 0=LSB comes from DSP pipeline (default) + * 1=LSB comes from io_rx[14] + */ + volatile uint32_t gpio_stream_enable; + } dsp_rx_regs_t; #define dsp_rx_regs ((dsp_rx_regs_t *) DSP_RX_BASE) diff --git a/usrp2/firmware/lib/u2_init.c b/usrp2/firmware/lib/u2_init.c index 948055694..713b2c321 100644 --- a/usrp2/firmware/lib/u2_init.c +++ b/usrp2/firmware/lib/u2_init.c @@ -51,13 +51,15 @@ get_hw_rev(void) bool u2_init(void) { - // Set GPIOs to inputs + // Set GPIOs to inputs, disable GPIO streaming hal_gpio_set_ddr(GPIO_TX_BANK, 0x0000, 0xffff); hal_gpio_set_ddr(GPIO_RX_BANK, 0x0000, 0xffff); hal_gpio_write(GPIO_TX_BANK, 0x0000, 0xffff); // init s/w output value to zero hal_gpio_write(GPIO_RX_BANK, 0x0000, 0xffff); + dsp_rx_regs->gpio_stream_enable = 0; // I, Q LSBs come from DSP + hal_io_init(); // init spi, so that we can switch over to the high-speed clock |