aboutsummaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorNick Foster <nick@nerdnetworks.org>2010-08-11 13:42:03 -0700
committerNick Foster <nick@nerdnetworks.org>2010-08-16 17:29:40 -0700
commitecc971c613d4a7dfe31bc142f99bfdba898d91eb (patch)
tree9eb42726e99b8885e5a1fcb82c1731439db48439 /firmware
parent20d1f96f9594e299f8aef78cc70a587d1d87e289 (diff)
downloaduhd-ecc971c613d4a7dfe31bc142f99bfdba898d91eb.tar.gz
uhd-ecc971c613d4a7dfe31bc142f99bfdba898d91eb.tar.bz2
uhd-ecc971c613d4a7dfe31bc142f99bfdba898d91eb.zip
IRQ-based SPI works. Don't try to do multiple transactions without waiting for results first. In fact, don't try to do
an I2C transaction while an SPI transaction is pending.
Diffstat (limited to 'firmware')
-rw-r--r--firmware/microblaze/apps/txrx_uhd.c7
-rw-r--r--firmware/microblaze/lib/spi.c23
-rw-r--r--firmware/microblaze/lib/spi.h8
3 files changed, 20 insertions, 18 deletions
diff --git a/firmware/microblaze/apps/txrx_uhd.c b/firmware/microblaze/apps/txrx_uhd.c
index 6fb01fec2..1dd6e80ac 100644
--- a/firmware/microblaze/apps/txrx_uhd.c
+++ b/firmware/microblaze/apps/txrx_uhd.c
@@ -194,7 +194,7 @@ void i2c_write_done_callback(void) {
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();
+ ctrl_data_out.data.spi_args.data = spi_get_data();
spi_done = true;
spi_register_callback(0);
}
@@ -245,8 +245,6 @@ void handle_udp_ctrl_packet(
******************************************************************/
case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:{
//transact
- 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
@@ -254,11 +252,10 @@ void handle_udp_ctrl_packet(
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,
- spicall //callback
+ get_spi_readback_data //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;
}
diff --git a/firmware/microblaze/lib/spi.c b/firmware/microblaze/lib/spi.c
index 33fcce05f..2a41a1bfa 100644
--- a/firmware/microblaze/lib/spi.c
+++ b/firmware/microblaze/lib/spi.c
@@ -22,6 +22,8 @@
void (*volatile spi_callback)(void); //SPI callback when xfer complete.
+static void spi_irq_handler(unsigned irq);
+
void
spi_init(void)
{
@@ -68,8 +70,10 @@ void spi_register_callback(void (*volatile callback)(void)) {
spi_callback = callback;
}
-void spi_irq_handler(void) {
- printf("SPI IRQ handler\n");
+static void spi_irq_handler(unsigned irq) {
+// printf("SPI IRQ handler\n");
+// uint32_t wat = spi_regs->ctrl; //read a register just to clear the interrupt
+ //spi_regs->ctrl &= ~SPI_CTRL_IE;
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
}
@@ -80,9 +84,12 @@ uint32_t spi_get_data(void) {
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;
+ int ctrl = SPI_CTRL_ASS | SPI_CTRL_IE | (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.
+ if(spi_regs->ctrl & SPI_CTRL_GO_BSY) {
+ printf("Async SPI busy!\n");
+ return false; //we don't wait on busy, we just return failure. we count on the host to not set up another transaction before the last one finishes.
+ }
// Tell it which SPI slave device to access
spi_regs->ss = slave & 0xffff;
@@ -90,14 +97,12 @@ spi_async_transact(int slave, uint32_t data, int length, uint32_t flags, void (*
// Data we will send
spi_regs->txrx0 = data;
+ spi_register_callback(callback);
+ pic_register_handler(IRQ_SPI, spi_irq_handler);
+
// 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 18699f21a..54618cedd 100644
--- a/firmware/microblaze/lib/spi.h
+++ b/firmware/microblaze/lib/spi.h
@@ -48,13 +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);
+//static void spi_irq_handler(unsigned irq);
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));
+
// ----------------------------------------------------------------
// Routines that manipulate the FLASH SPI BUS
// ----------------------------------------------------------------