SAMD21 SPI Async - Transfer Error Cannot Recover

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For several days I've been learning the SAM21 SPI Async driver.  I have it mostly working but have one last thing I'm struggling to understand; clearing a failed transfer. FYI, I'm using the When "Atmel Start Project" to start the config of the project in AS7. Please correct me on anything I have wrong.

 

When calling the spi_s_async_init() function you pass it a buffer and a length. I've come to assume this is the length the driver expects to receive on each transfer (from chip select down to chip select up). In the included code I've list what I think each of the callbacks do. Everything works great if the message clocks in fully. If you a byte or more short the "error" callback is called, and I assume I should do something there. I've tried reseting the error, but that doesn't work. I have to reset the controller to get transfers to work again.

 


#include "driver_examples.h"
#include "driver_init.h"
#include "utils.h"


#define BUFFER_LEN 128
static uint8_t SPI_0_rx_buf[BUFFER_LEN];
static uint8_t SPI_0_tx_buf[BUFFER_LEN];

volatile uint32_t msg=0;
volatile uint32_t rx=0;
volatile uint32_t tx=0;
volatile uint32_t err=0;

static void complete_cb_SPI_0(const struct spi_s_async_descriptor *const desc)
{	
	msg++; //increment the global msg number
	SPI_0_update(); //for next transaction	
}

static void tx_cb_SPI_0(const struct spi_s_async_descriptor *const desc)
{
	//this seems to get called each time you call "io_write()".
	tx++; //increment the global tx number
}
static void rx_cb_SPI_0(const struct spi_s_async_descriptor *const desc)
{	
	//this seems to be called on every byte received as SPI slave
	rx++; //increment the global rx number
}
static void err_cb_SPI_0(const struct spi_s_async_descriptor *const desc)
{
	//never get any errors if message completes, must error if less bytes / clock than expected
        SPI_0.error = false;
        SPI_0.busy = false;
        SPI_0_update(); //get ready for the next message
	err++;
}

void SPI_0_setup(void){
	//Using Adafruit Metro M0 Express, Pins are:
	//MISO PA04 - A3
	//MOSI PA06 - D8
	//CLK  PA07 - D9
	//SS   PA05 - A4	
	spi_s_async_init(&SPI_0, SERCOM0, (uint8_t *)SPI_0_rx_buf, BUFFER_LEN); //This length is the expected msg length
	//register callbacks
	spi_s_async_register_callback(&SPI_0, SPI_S_CB_COMPLETE, (FUNC_PTR)complete_cb_SPI_0);
	spi_s_async_register_callback(&SPI_0, SPI_S_CB_TX, (FUNC_PTR)tx_cb_SPI_0);
	spi_s_async_register_callback(&SPI_0, SPI_S_CB_RX, (FUNC_PTR)rx_cb_SPI_0);
	spi_s_async_register_callback(&SPI_0, SPI_S_CB_ERROR, (FUNC_PTR)err_cb_SPI_0);
	spi_s_async_enable(&SPI_0); //enable the interrupts
	for(uint8_t i=0; i<BUFFER_LEN; i++){
		SPI_0_tx_buf[i] = i; //fill buffer with index numbers for something to verify
	}
	SPI_0_update(); //run the update to put the first msg number on the front
}

void SPI_0_update(void)
{
	//transaction completed, read the data and get ready for the next one
	//move rx data out of SPI_0_rx_buf
	
	//do stuff here
	
	//move tx data into SPI_0_rx_buf
	//for now just put the message number at the front of the tx data
	memcpy(SPI_0_tx_buf, &msg, sizeof(msg));
	
	struct io_descriptor *io;
	spi_s_async_get_io_descriptor(&SPI_0, &io);
	//need to call io_write after every transaction or tx data is sent from rx buffer
	//also if last message not complete, the "busy" flag is set and writes do not work correctly
	io_write(io, SPI_0_tx_buf, BUFFER_LEN);
}

 

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

spi_s_async_enable maybe?

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I call this in the setup function. Are you suggesting I disable the driver then re-enable?

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm thinking part of the error handling in the driver already looks like a disable, might cure that with another enable.

/Lars