diff options
| -rw-r--r-- | firmware/microblaze/apps/txrx_uhd.c | 30 | ||||
| -rw-r--r-- | firmware/microblaze/lib/spi.c | 41 | ||||
| -rw-r--r-- | firmware/microblaze/lib/spi.h | 7 | 
3 files changed, 72 insertions, 6 deletions
| diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c index bdb793fd9..82e2e2b6f 100644 --- a/firmware/microblaze/apps/txrx_uhd.c +++ b/firmware/microblaze/apps/txrx_uhd.c @@ -174,7 +174,8 @@ void handle_udp_data_packet(  //setup the output data  static usrp2_ctrl_data_t ctrl_data_out; -static struct socket_address i2c_src, i2c_dst; +static struct socket_address i2c_src; +static struct socket_address spi_src;  static volatile bool i2c_done = false;  void i2c_read_done_callback(void) { @@ -190,6 +191,14 @@ void i2c_write_done_callback(void) {    i2c_register_callback(0);  } +static volatile bool spi_done = false; +static volatile uint32_t spi_readback_data; +void get_spi_readback_data(void) { +  spi_readback_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 @@ -236,20 +245,24 @@ void handle_udp_ctrl_packet(       ******************************************************************/      case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:{              //transact -            uint32_t result = spi_transact( -                (ctrl_data_in->data.spi_args.readback == 0)? SPI_TXONLY : SPI_TXRX, +            uint32_t result; +            void (*volatile spicall)(void) = (ctrl_data_in->data.spi_args.readback == 0) ? 0 : get_spi_readback_data; //only need a callback if we're doing readback +            bool success = spi_async_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 | -                (ctrl_data_in->data.spi_args.miso_edge == USRP2_CLK_EDGE_RISE)? SPIF_LATCH_RISE : SPIF_LATCH_FALL +                (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, +                spicall //callback              );              //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)); +//        send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out));          break;      /******************************************************************* @@ -512,6 +525,11 @@ main(void)        //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)); +    } +      int pending = pic_regs->pending;		// poll for under or overrun      if (pending & PIC_UNDERRUN_INT){ diff --git a/firmware/microblaze/lib/spi.c b/firmware/microblaze/lib/spi.c index bef808e57..4371b9b8a 100644 --- a/firmware/microblaze/lib/spi.c +++ b/firmware/microblaze/lib/spi.c @@ -17,6 +17,9 @@  #include "spi.h"  #include "memory_map.h" +#include "nonstdio.h" + +void (*volatile spi_callback)(void); //SPI callback when xfer complete.  void  spi_init(void)  @@ -59,3 +62,41 @@ spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags    else      return 0;  } + +void spi_register_callback(void (*volatile callback)(void)) { +  spi_callback = callback; +} + +void spi_irq_handler(void) { +  printf("SPI IRQ handler\n"); +  if(spi_callback) spi_callback(); //we could just use the PIC to register the user's callback, but this provides the ability to do other things later +} + +uint32_t spi_get_data(void) { +  return spi_regs->txrx0; +} + +bool  +spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void)) { +  flags &= (SPI_CTRL_TXNEG | SPI_CTRL_RXNEG); +  int ctrl = SPI_CTRL_ASS | (SPI_CTRL_CHAR_LEN_MASK & length) | flags; + +  if(spi_regs->ctrl & SPI_CTRL_GO_BSY) return false; //we don't wait on busy, we just return failure. + +  // Tell it which SPI slave device to access +  spi_regs->ss = slave & 0xffff; + +  // Data we will send +  spi_regs->txrx0 = data; + +  // Run it -- write once and rewrite with GO set +  spi_regs->ctrl = ctrl; +  spi_regs->ctrl = ctrl | SPI_CTRL_GO_BSY; + +  spi_regs->ctrl |= SPI_CTRL_IE; //we do these here so that we don't have to start the PIC before the SPI sets up the clocks on startup +  pic_register_handler(IRQ_SPI, spi_irq_handler); + +  spi_register_callback(callback); + +  return true; +} diff --git a/firmware/microblaze/lib/spi.h b/firmware/microblaze/lib/spi.h index 01e4d26fd..18699f21a 100644 --- a/firmware/microblaze/lib/spi.h +++ b/firmware/microblaze/lib/spi.h @@ -48,6 +48,13 @@ void spi_wait(void);  uint32_t  spi_transact(bool readback, int slave, uint32_t data, int length, uint32_t flags); +bool  +spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*volatile callback)(void)); + +uint32_t spi_get_data(void); +void spi_irq_handler(void); +void spi_register_callback(void (*volatile callback)(void)); +  // ----------------------------------------------------------------  // Routines that manipulate the FLASH SPI BUS  // ---------------------------------------------------------------- | 
