Using SERCOM SPI library to make a spi slave

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

Hi everyone,

I am quite new around here, and I am having trouble with ASF libraries:

I need to set up a spi slave on a SAMD21 (using samd21 xplained board), I am using the SERCOM SPI library, added from ASF wizard.

Until now, I made the library work as master (using an arduino as slave).

 

this is my adaptation of the master example, so I surely made some stupid mistake...

 

i tryed to set up a callback, but i don't know what can be missing...

#include <asf.h>

struct spi_module spi_slave_instance;

struct spi_slave_inst slave;

void configure_spi_slave_callbacks(void);
void configure_spi_slave(void);

static void callback_spi_slave( struct spi_module *const module){
//i think it should enter here when the master send something (it does not)
}

void configure_spi_slave_callbacks(void){
	spi_register_callback(&spi_slave_instance, callback_spi_slave,
			SPI_CALLBACK_BUFFER_TRANSCEIVED);
	spi_enable_callback(&spi_slave_instance, SPI_CALLBACK_BUFFER_RECEIVED);

}

void configure_spi_slave(void){
	struct spi_config config_spi_slave;
	spi_get_config_defaults(&config_spi_slave);
	config_spi_slave.mode = SPI_MODE_SLAVE;

//i copied this 2 lines looking on the web
	config_spi_slave.mode_specific.slave.preload_enable = true;
	config_spi_slave.mode_specific.slave.frame_format = SPI_FRAME_FORMAT_SPI_FRAME;

//this configuration worked for the spi master, on the ext2, so i am keeping this
	config_spi_slave.mux_setting = EXT2_SPI_SERCOM_MUX_SETTING;
	config_spi_slave.pinmux_pad0 = EXT2_SPI_SERCOM_PINMUX_PAD0;
	config_spi_slave.pinmux_pad1 = PINMUX_UNUSED;
	config_spi_slave.pinmux_pad2 = EXT2_SPI_SERCOM_PINMUX_PAD2;
	config_spi_slave.pinmux_pad3 = EXT2_SPI_SERCOM_PINMUX_PAD3;
	spi_init(&spi_slave_instance, EXT2_SPI_MODULE, &config_spi_slave);
	spi_enable(&spi_slave_instance);

}

int main(void){
	system_init();
	configure_spi_slave();
	configure_spi_slave_callbacks();
	while (true) {}
}

 

Then one last question, I have seen Atmel Start online, but it seems to me not compatible with ASF, what is the difference between the two? which one should I use?

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

There is a ASF Quick start project with SPI slave callback, why not start with that. I have personally been ok using ASF (version 3) so I have no real experience with Atmel Start (which is newer and based on ASF4). There is some introduction here:
http://atmel-studio-doc.s3-websi...

/Lars

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

FWIW I have recently (in the past 2 weeks) been using the newer START and ASF4 to try to get an ATSAMG55 running the SPI interface as a master.  The documentation of ASF4 is very sparse and incomplete.  I managed to locate an API reference manual that Microchip says is in alpha release.  You can find it here: http://atmel-studio-doc.s3-website-us-east-1.amazonaws.com/webhelp/GUID-2A8AADED-413E-4021-AF0C-D99E61B8160D-en-US-1/index.html?GUID-819376C9-5C19-4F1E-9320-ED29CF2A0627

 

Read the introduction to ASF4 for their vision of what this will be.  This document is not easy to find by a web search and although it is referenced by the START User Guide it is not directly linked.  This ASF4 API Reference Manual does come up when you are using the START tool with a device driver and you click on the user guide button (at least it does for some drivers).

 

If you are patient and like to blaze trails then use the new START and ASF4 but be warned that you may need to do a lot of trial and error development.  I have been looking at the example projects and working from there.  Unfortunately for SPI and the G55, the examples for a master SPI device only use the write and not a read and it doesn't properly control the slave select.  It looks to me like the slave select terminates after the callback on the final byte write to the transmit data register but before the data has completed serial transmission.

 

If you are under pressure then use the older ASF3 since that has better documentation existing. For ASF3 and the ATSAMG55 there was an example project for SPI that set the XPlained board as a SPI slave.  It allowed it to change to a SPI master.  This then allowed two XPlained boards to transfer data.  I would start looking at that.  I think it may be similar for the D21.

 

 

Last Edited: Wed. Aug 30, 2017 - 04:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for you answer, Lajon and tarribred,

 

I found an example of spi slave implementation, and it is quite working!

 

I am using an arduino as master, and datas gets exchanged, but they are not received correctly.

i think it may be the SPI mode: 

 

here is atmel spi doc

http://www.atmel.com/Images/Atmel-42115-SAM-Serial-Peripheral-Interface-Driver-Sercom-SPI_ApplicationNote_AT03255.pdf (go page 9)

and here is arduino spi doc

https://www.arduino.cc/en/Reference/SPI

 

atmel talks about "Leading Edge" and  "Trailing Edge" meanwhile arduino has "Output Edge" and "Data Capture",

i notice that mode 0 and 2 have rising and falling switched in the two libraries... 

I have tried using mode 3

 

any idea for a solution? online i don't found anyone who made this two board talk to each other...

 

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

I have since learned that I had to flush the buffer of the spi port before I did the read; I did this by reading one byte before starting the read by calling _spi_m_async_read_one() from the hpl_spi.c.  I'm assuming there was some data there from a previous write and so when I did the read it just read in old data from a buffer and not the new data I wanted.  I also learned that in ASF4 you have to control the SPI slave select manually; that is written in the documentation that automatic select is not supported.

 

In my case, I am using the SPI port in master async mode.

 

My process is something like:

1) flush the spi rx buffer using _spi_m_async_read_one(); also clear any old flags that may be set in a callback function

2) assert the slave select; using a gpio to manually control the pin

3) use spi_m_asyn_transfer() to simultaneously write and read the port for the amount of bytes I want to read or use io_read()

4) in the callback for the transfer complete; I set a boolean flag (make it volatile type)

5) The callback happens when the final byte is being transferred but before the transfer is completed.. so..

6) use the hri_spi-get_SR_TXEMPTY_bit() function to wait until the SPI transmit is idle

7) deassert the slave select

 

 

 

 

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

I just recently found that there is a new and preliminary PDF document describing START and ASF4 APIs.  You can find it on Google search for ASF4 START API Reference Manual.

 

Here is the link I found.

http://ww1.microchip.com/downloa...