diff options
-rw-r--r-- | usrp2/firmware/Makefile.common | 2 | ||||
-rw-r--r-- | usrp2/firmware/lib/Makefile.am | 4 | ||||
-rw-r--r-- | usrp2/firmware/lib/bsm12.c | 201 | ||||
-rw-r--r-- | usrp2/firmware/lib/bsm12.h | 80 | ||||
-rw-r--r-- | usrp2/firmware/lib/buffer_state.c | 21 | ||||
-rw-r--r-- | usrp2/firmware/lib/buffer_state.h | 33 | ||||
-rw-r--r-- | usrp2/firmware/lib/dbsm.c | 10 |
7 files changed, 341 insertions, 10 deletions
diff --git a/usrp2/firmware/Makefile.common b/usrp2/firmware/Makefile.common index b90696fea..d45576201 100644 --- a/usrp2/firmware/Makefile.common +++ b/usrp2/firmware/Makefile.common @@ -23,7 +23,7 @@ HAL_IO = -DHAL_IO_USES_UART AM_CPPFLAGS = $(HAL_IO) $(STD_INCLUDES) -STD_CFLAGS = -Wall -Werror-implicit-function-declaration -mxl-soft-div -msoft-float +STD_CFLAGS = --std=gnu99 -Wall -Werror-implicit-function-declaration -mxl-soft-div -msoft-float AM_CFLAGS = $(STD_CFLAGS) -mxl-soft-mul -mxl-barrel-shift #AM_CFLAGS = $(STD_CFLAGS) -mxl-soft-mul -mxl-barrel-shift -mxl-gp-opt -G 16384 diff --git a/usrp2/firmware/lib/Makefile.am b/usrp2/firmware/lib/Makefile.am index 854539c99..027b6ac9b 100644 --- a/usrp2/firmware/lib/Makefile.am +++ b/usrp2/firmware/lib/Makefile.am @@ -25,7 +25,9 @@ libu2fw_a_SOURCES = \ abort.c \ ad9510.c \ ad9777.c \ + bsm12.c \ buffer_pool.c \ + buffer_state.c \ clocks.c \ db_basic.c \ db_init.c \ @@ -62,7 +64,9 @@ noinst_HEADERS = \ ad9777.h \ ad9777_regs.h \ bool.h \ + bsm12.h \ buffer_pool.h \ + buffer_state.h \ clocks.h \ db.h \ db_base.h \ diff --git a/usrp2/firmware/lib/bsm12.c b/usrp2/firmware/lib/bsm12.c new file mode 100644 index 000000000..25c5a3fda --- /dev/null +++ b/usrp2/firmware/lib/bsm12.c @@ -0,0 +1,201 @@ +/* -*- 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/>. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "bsm12.h" +#include "memory_map.h" +#include "buffer_pool.h" +#include "bool.h" +#include "nonstdio.h" +#include "buffer_state.h" +#include <stdlib.h> + +static uint32_t last_send_ctrl[NBUFFERS]; + +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_idle = true; + sm->tx_idle[0] = true; + sm->tx_idle[1] = true; + + 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; + + 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) +{ + 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; +} + +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; + + bp_clear_buf(sm->buf0 + 0); + bp_clear_buf(sm->buf0 + 1); + bp_clear_buf(sm->buf0 + 2); + + sm->rx_idle = false; + sm->tx_idle[0] = true; + sm->tx_idle[1] = true; + 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) +{ +} + +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/usrp2/firmware/lib/bsm12.h b/usrp2/firmware/lib/bsm12.h new file mode 100644 index 000000000..8649f1176 --- /dev/null +++ b/usrp2/firmware/lib/bsm12.h @@ -0,0 +1,80 @@ +/* -*- 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> + +/*! + * 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 zero, 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; + uint8_t rx_idle; + uint8_t tx_idle[2]; + buf_cmd_args_t recv_args; + buf_cmd_args_t send_args[2]; + bsm12_inspector_t inspect; + uint32_t bps_error; + uint32_t bps_done; + uint32_t bps_error_or_done; + 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) + int last_line_adj; +}; + +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/usrp2/firmware/lib/buffer_state.c b/usrp2/firmware/lib/buffer_state.c new file mode 100644 index 000000000..cea5022f4 --- /dev/null +++ b/usrp2/firmware/lib/buffer_state.c @@ -0,0 +1,21 @@ +/* -*- 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/>. + */ + +#include "buffer_state.h" + +buffer_state_t buffer_state[NBUFFERS]; diff --git a/usrp2/firmware/lib/buffer_state.h b/usrp2/firmware/lib/buffer_state.h new file mode 100644 index 000000000..f855dc4ae --- /dev/null +++ b/usrp2/firmware/lib/buffer_state.h @@ -0,0 +1,33 @@ +/* -*- 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_BUFFER_STATE_H +#define INCLUDED_BUFFER_STATE_H + +#include "memory_map.h" + +typedef enum { + BS_EMPTY, + BS_FILLING, + BS_FULL, + BS_EMPTYING, +} buffer_state_t; + +extern buffer_state_t buffer_state[NBUFFERS]; + +#endif /* INCLUDED_BUFFER_STATE_H */ diff --git a/usrp2/firmware/lib/dbsm.c b/usrp2/firmware/lib/dbsm.c index b11d16824..cfe911538 100644 --- a/usrp2/firmware/lib/dbsm.c +++ b/usrp2/firmware/lib/dbsm.c @@ -25,17 +25,9 @@ #include "buffer_pool.h" #include "bool.h" #include "nonstdio.h" +#include "buffer_state.h" #include <stdlib.h> -typedef enum { - BS_EMPTY, - BS_FILLING, - BS_FULL, - BS_EMPTYING, -} buffer_state_t; - -buffer_state_t buffer_state[NBUFFERS]; - bool dbsm_nop_inspector(dbsm_t *sm, int buf_this) { |