commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r10867 - gnuradio/branches/developers/eb/tims_timer/us


From: eb
Subject: [Commit-gnuradio] r10867 - gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps
Date: Fri, 17 Apr 2009 12:28:59 -0600 (MDT)

Author: eb
Date: 2009-04-17 12:28:59 -0600 (Fri, 17 Apr 2009)
New Revision: 10867

Added:
   gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/tims_timer.c
Modified:
   gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/
   gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/Makefile.am
Log:
Firmware for Tim's Timer, ready to test.



Property changes on: 
gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps
___________________________________________________________________
Modified: svn:ignore
   - *-stamp
*.a
*.bin
*.dump
*.log
*.rom
*.map
.deps
Makefile
Makefile.in
aclocal.m4
autom4te.cache
blink_leds
blink_leds2
build
compile
config.h
config.h.in
config.log
config.status
configure
depcomp
echo
eth_test
gen_eth_packets
ibs_rx_test
ibs_tx_test
install-sh
libtool
ltmain.sh
missing
py-compile
rcv_eth_packets
run_tests.sh
stamp-h1
test1
test_phy_comm
timer_test
buf_ram_test
buf_ram_zero
hello
test_printf
test_spi
test_i2c
gen_pause_frames
test_serdes
rx_only
tx_only
tx_standalone
tx_drop
tx_drop2
tx_drop_rate_limited
test_lsdac
test_lsadc
read_dbids
test_db_spi
ramp_lsdac
eth_to_serdes
serdes_to_dsp
sd_gentest
sd_bounce
can_i_sub
tx_only_v2
rx_only_v2
txrx
eth_serdes
serdes_txrx
set_hw_rev
test_sd
factory_test
test_ram
mimo_tx
mimo_tx_slave
burn_dbsrx_eeprom

   + *-stamp
*.a
*.bin
*.dump
*.log
*.rom
*.map
.deps
Makefile
Makefile.in
aclocal.m4
autom4te.cache
blink_leds
blink_leds2
build
compile
config.h
config.h.in
config.log
config.status
configure
depcomp
echo
eth_test
gen_eth_packets
ibs_rx_test
ibs_tx_test
install-sh
libtool
ltmain.sh
missing
py-compile
rcv_eth_packets
run_tests.sh
stamp-h1
test1
test_phy_comm
timer_test
buf_ram_test
buf_ram_zero
hello
test_printf
test_spi
test_i2c
gen_pause_frames
test_serdes
rx_only
tx_only
tx_standalone
tx_drop
tx_drop2
tx_drop_rate_limited
test_lsdac
test_lsadc
read_dbids
test_db_spi
ramp_lsdac
eth_to_serdes
serdes_to_dsp
sd_gentest
sd_bounce
can_i_sub
tx_only_v2
rx_only_v2
txrx
eth_serdes
serdes_txrx
set_hw_rev
test_sd
factory_test
test_ram
mimo_tx
mimo_tx_slave
burn_dbsrx_eeprom
tims_timer


Modified: 
gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/Makefile.am
===================================================================
--- gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/Makefile.am  
2009-04-17 18:09:11 UTC (rev 10866)
+++ gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/Makefile.am  
2009-04-17 18:28:59 UTC (rev 10867)
@@ -43,6 +43,7 @@
        test_lsadc \
        test_lsdac \
        timer_test \
+       tims_timer \
        tx_standalone \
        txrx \
        factory_test \
@@ -63,6 +64,7 @@
 serdes_txrx_SOURCES = serdes_txrx.c app_common_v2.c
 mimo_tx_SOURCES = mimo_tx.c mimo_app_common_v2.c
 mimo_tx_slave_SOURCES = mimo_tx_slave.c app_common_v2.c
+tims_timer_SOURCES = tims_timer.c
 
 noinst_HEADERS = \
         app_common_v2.h \

Added: 
gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/tims_timer.c
===================================================================
--- gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/tims_timer.c 
                        (rev 0)
+++ gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/tims_timer.c 
2009-04-17 18:28:59 UTC (rev 10867)
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "clocks.h"
+
+/*
+ * Tim's Timer :-)
+ *
+ *
+ * incoming packets:
+ *
+ * [14-byte eth header][2-byte 0xffff]
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |        sub-opcode             |   reply payload len in bytes  |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            ignored                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~                            variable                           ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *
+ * Outgoing packets:
+ *
+ * [14-byte eth header][2-byte 0xffff]
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |        sub-opcode             |   reply payload len in bytes  |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                           FPGA time                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ~                            variable                           ~
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ */
+
+/*
+ * Buffers 2 and 3 are used to double-buffer the eth Rx to eth Tx flow
+ */
+#define        ETH_BUF_0       2
+#define ETH_BUF_1      3
+
+volatile bool link_is_up = false;      // eth handler sets this
+
+/*
+ * ================================================================
+ * Slightly modified version of the dbsm to handle variable length
+ * replies.
+ * ================================================================
+ */
+
+/*
+ * Double Buffering State Machine
+ */
+
+#include "dbsm.h"
+#include "memory_map.h"
+#include "buffer_pool.h"
+#include "bool.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];
+
+uint16_t s_send_len[NBUFFERS];         // Added for Tim's timer
+
+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;
+
+  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];
+}
+
+
+#if 0
+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));
+}
+#else
+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(s_send_len[bufno]));
+}
+#endif
+
+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);
+
+    if (status & (BPS_ERROR(sm->buf0 ^ 1)))
+      dbsm_error_helper(sm, sm->buf0 ^ 1);
+  }
+
+  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
+  dsp_tx_regs->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);
+    dsp_tx_regs->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);
+    dsp_tx_regs->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)
+{
+  dsp_rx_regs->clear_state = 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)
+      ;
+  }
+}
+
+/*
+ * ================================================================
+ *   configure double buffering state machine (eth -> eth)
+ * ================================================================
+ */
+
+// Receive from ethernet
+buf_cmd_args_t eth_recv_args = {
+  PORT_ETH,
+  0,
+  BP_LAST_LINE
+};
+
+// send to ethernet
+buf_cmd_args_t eth_send_args = {
+  PORT_ETH,
+  0,
+  0                    // filled in from last_line register
+};
+
+dbsm_t eth_sm;         // the state machine
+
+/*
+ * This is called when the eth Rx chain has filled in a packet.
+ * We overwrite with the FPGA time, and kludge up the length.
+ */
+bool 
+tims_pkt_inspector(dbsm_t *sm, int buf_this)   // returns false
+{
+  uint32_t *p = buffer_ram(buf_this);
+
+  uint32_t *payload = &p[4];   // skip 14-bytes of eth hdr + 2 bytes of pad
+  
+  int subopcode = payload[0] >> 16;
+  int payload_reply_len = ((payload[0] & 0xffff) + 3) / 4;
+
+  // tell modified dbsm the length to send
+  s_send_len[buf_this] = payload_reply_len + 4;        // len of complete 
reply pkt in lines
+
+  // setup MAC src and dst addresses
+  struct {
+    u2_mac_addr_t dst;
+    u2_mac_addr_t src;
+  } __attribute__((aligned (4))) mac_hdr;      // 12-bytes (word aligned)
+
+  mac_hdr.dst = ((u2_eth_hdr_t *)p)->src;
+  mac_hdr.src = *ethernet_mac_addr();
+  memcpy_wa(p, &mac_hdr, sizeof(mac_hdr));     // buffer is only word-writable
+
+
+  payload[1] = timer_regs->time;       // overwrite w/ time
+
+  // FIXME
+  return false;                // we didn't handle the packet
+}
+
+
+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);
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  uint32_t  status = buffer_pool_status->status;
+
+  dbsm_process_status(&eth_sm, status);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nTim's Timer\n");
+  print_mac_addr(ethernet_mac_addr()->addr);
+  newline();
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+
+  // initialize double buffering state machine for ethernet -> ethernet
+
+  dbsm_init(&eth_sm, ETH_BUF_0,
+           &eth_recv_args, &eth_send_args,
+           tims_pkt_inspector);
+
+
+  // kick off the state machine
+  dbsm_start(&eth_sm);
+
+  while(1){
+    buffer_irq_handler(0);
+  }
+}


Property changes on: 
gnuradio/branches/developers/eb/tims_timer/usrp2/firmware/apps/tims_timer.c
___________________________________________________________________
Added: svn:eol-style
   + native





reply via email to

[Prev in Thread] Current Thread [Next in Thread]