SAMB11 SPI transmission repeating chars

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I rewrote the SPI rx and tx ISRs for a SPI slave instance on  SAMB11 a few weeks ago, because the ASF implementations were too slow.  They've been working fairly well, but recently I made some changes to some of the SPI receiving code (mostly about how and when I pull data out of the ring buffer I set up for the ISR to write into, and nothing to do with the SPI hardware itself, or with TX).  Now, when I transmit more than a few chars (5-ish, though it varies), the SPI hardware seems to duplicate one of the bytes and replaces following bytes with the duplicated byte.  For example, it will turn

foo-bar-baz

into

foo-bbbbbb

- same number of chars, but repeating one from the stream.  I've instrumented the ISR to copy data into a debug buffer while transmitting (so I can look afterward), and it has all the correct bytes.  I've verified with a logic analyzer that the samb11 spi slave is putting the bad bytes on the wire, it's not happening at the receiver.

Here's the ISR:

static void
spi_mw_tx_isr_handler(void)
{
    uint32_t intflags = BT_SPI->TRANSMIT_STATUS.reg;
    intflags &= BT_SPI->TX_INTERRUPT_MASK.reg;

    static bool led = false;

    if (intflags & SPI_TRANSMIT_STATUS_TX_FIFO_NOT_FULL_1) {
        /* write even when we get a -1 result - that'll be a dummy
           byte */
        int r = spi_mw_buf_get(&spi_mw_tx_buf);
        BT_SPI->TRANSMIT_DATA.reg = r & SPI_TRANSMIT_DATA_Msk;
        if (r >= 0) {
            _spi_push_debug(r);
        }
    }

    led = !led;
    gpio_pin_set_output_level(BT_DEBUG_LED3, led);

    /* Not sure if this should even happen - this means the slave
       select is high, and I doubt we'd get an interrupt in that case */
    if (intflags & SPI_TRANSMIT_STATUS_TX_FIFO_EMPTY) {
        spi_mw_tx_empty++;
    }
}

 

spi_mw_buf_get() reads from the ring buffer and returns -1 if there is no data.  _spi_push_debug() sticks the sent byte in a debug buffer for later dumping to stdout.

This seemed to be working before unrelated code changes - though I could see timing issues affecting things maybe?  There's a lot going on under the hood with the SAMB11 - does anyone know of something to help diagnose this further?