[ATSAMD51J18A-AU] SERCOM - SPI Communication API

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

Hi,

In my project we have to develop SPI communication between jethro processor (ARM based) and ATSAMD51J18A controller (SAM controller) .

In data sheet it is mentioned that SERCOM SPI interface is used in SAMD51.

We referred the ASF4 API reference manual to find APIs for SERCOM SPI interface.

_http://ww1.microchip.com/downloa...

 

Found some predefined API's for SPI driver. We have created new project by adding controller(SAMD51) and SPI_0 software component using Atmel Start configuration and generated the solution. In the SPI module preview code (in atmel start) found the same APIs ,which we referred from the API reference manual.

we tried some basic code to implement simple communication between master and slave (asynchronous spi slave driver has chosen) using the APIs mentioned in the API reference manual and preview code in atmel start.

Example code flow:

---------------

struct io_descriptor *io;

/*To get io_descriptor structure details for SPI module */

spi_s_async_get_io_descriptor(&SPI_0, &io);

/* To register the call back functions for TX and RX

spi_s_async_register_callback(&SPI_0, SPI_S_CB_TX, (FUNC_PTR)complete_cb_tx_SPI_0);

spi_s_async_register_callback(&SPI_0, SPI_S_CB_RX, (FUNC_PTR)complete_cb_rx_SPI_0);

/* Enabling SPI module */

spi_s_async_enable(&SPI_0);

/* Read the received data from master */

io_read(io, &ReadData,1);

if(ReadData == 0xAA) /*0xAA data received from Host*/

{

/* Send the data to master */

io_write(io, &ReturnValue,1);

}

spi_s_async_disable(&SPI_0);

Will it work or any other APIs are there for SERCOM SPI interface in SAMD51 ?

Jana8153

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

Since you're using the async version of the spi api I don't think the code you posted will work. Using the sync api I think you would be able to get your response immediately after the call to io_read, but the async api doesn't block, so the "data from host" won't be available until your complete_cb_rx_SPI_0 is called.

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

cholz wrote:

Since you're using the async version of the spi api I don't think the code you posted will work. Using the sync api I think you would be able to get your response immediately after the call to io_read, but the async api doesn't block, so the "data from host" won't be available until your complete_cb_rx_SPI_0 is called.

 

Please refer our complete code which will verify the SPI communication between slave and Host. so the code will work like, if the slave received 0xAA from master, it will transmit 0x55 to master(as an ack) and if the data is not 0xAA then it will transmit 0x77 to master. While configuring using Atmel start, SPI configured as transmit byte as MSB.

 

But when i am sending 0xAA from host then slave transmitting 0x7F. Do you know why it is? 

-----------------------------------------------------------------------

static void complete_cb_rx_SPI_0(const struct spi_s_async_descriptor *const desc)
{
    io_read(io, &ReadData,1); 
}

void spi_start(void)
{
    spi_s_async_get_io_descriptor(&SPI_0, &io);                                           /* Get io descriptor structure parameters*/

    spi_s_async_register_callback(&SPI_0, SPI_S_CB_TX, (FUNC_PTR)complete_cb_tx_SPI_0);   /* Register call back function for TX*/
    spi_s_async_register_callback(&SPI_0, SPI_S_CB_RX, (FUNC_PTR)complete_cb_rx_SPI_0);   /* Register call back function for RX*/
    
    spi_s_async_enable(&SPI_0);                                                           /* Enabling SPI module */
    
}

int main(void)
{
    uint8_t ReturnValue=0x55; /* Example return value to verify data transfer */
    uint8_t Err_value=0x77;   /* Error value*/
           
    /* Initializes MCU, drivers and middleware */
    atmel_start_init();
    
    /*To register callback function & enable spi */
    spi_start();
    

    while (1) 
    {
        if(ReadData != 0 )
        {
            if(Ref_Value == ReadData)                 /*command received from Host*/
            {
                io_write(io, &ReturnValue,1);
            }
            
            else
            {
                io_write(io, &Err_value,1);
            }
        }
        
            
    }
}

 

As per datasheet, whenever SPI received 1 byte of data then _cb_rx_SP I_0 will be called. Is it correct? We have used async API, because it never gets blocked, since its based call back functions.

 

Also, is it possible to configure the SPI slave mode using DMA ? because i wants to transmit multi bytes from SAMD51 to Host. Is there any option available to support multiple read/write in SAMd51.

 

Only i am able to find Salve Sync and Slave Async drivers in ASF4 manual.

 

 

 

Jana8153

Last Edited: Wed. Nov 28, 2018 - 03:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I have developed the firmware for spi slave communication to receive one byte data from master and return one byte data to master.

Here the master is Jethro carrier. Slave- ATSAMD51J18A.

 

1.Master will send 0xAA to slave , after receiving 0xAA slave will return 0x56 (For 1st TX),0x36 (For 2nd TX),0x56 0x36.... alternatively to master.

2.if master sends any other data (except 0xAA) , slave will return 0x99.

 

In this case,

 

we have probed the SPI lines CLK, MOSI and MISO pins and found that there was the possibility of a bug in ASF library. 

 

Please find the steps which we followed, 

 

1st time.: When master sends 0xAA to slave. The slave should send 0x56 for first time. But it sends 0x00 to master.  

2nd time: When master sends 0xAA to slave. The slave should send 0x36 to master. But it sends 0xAA to master. 

3rd time: When master sends 0xAA to slave. Slave sends 0x56 to master.This is expected. 

4th time: When master sends 0xAA to slave. Slave sends 0x36 to master. This is also expected.

 

We are not getting proper data from the slave for the first two times. From 3 rd time onwards, we are getting proper data. 

If you refer the screenshots, you can see that all the times the slave receives proper data from the master with respect to the serial clock. 

 

We have checked with different data's and noticed that the first two times we are getting data which is not sent before. Any buffer is not cleared in ASF code?  

 

please check the below screenshots which is in order 1,2,3..

 

Jana8153

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

There is no way for the slave to see the 0xAA and respond to that in the same transfer (e.g., in your first screenshot), it can at best respond when the master sends another byte. 

This is the reason a SPI transaction is often some command from the master and then the master is required to send dummy bytes to clock out the response from the slave.

It is possible to preload the slave but this is then unconditional, e.g., in your first screenshot it would be possible to have some fixed value from the slave but it will not be possible to have that depend on what the master sent.

 

In your 2:nd screenshoot it's clear the slave has still not produced something to be sent (the old value in the shift register is sent), I don't know the reason for that. Could be related to this:

After DATA is written it takes up to three SCK clock cycles until the content of DATA is ready to be loaded

into the shift register on the next character boundary.

/Lars

 

 

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

From your above comments, we understood that for the first SPI transmission since slave doesn't have data, it will send 0x00. Then slave will reply on the next 8bits means first

transmission response we will get in next transmission only, since the first time we are getting 0x00. 

 

We have added the 200 us (microseconds ) delay before writing the data and noticed that we are able to get the data properly from the second transmission. Is it correct? 

If we remove the delay, then we are getting proper data in 3rd time only (first time 0x00, second time - previously received character is transmitted) 

 

But for every new transmission data, the first time we are not getting proper data. For example, 

 

1 st time : master sends 0xAA. Slave sends 0x00. 
2 nd time : master sends 0xAA. Slave sends 0x56 (with delay before IOwrite) 
3rd time : master sends 0xAA. Slave sends 0x36 
4th time : Master sends 0xFF. Slave should send 0x99. But slave sends 0x56 <- New transmission data 
5th time : Master sends 0xFF. Slave sends 0x99. 

Please refer the spi_write_with_delay_200us.PNG and spi_write_without_delay.PNG screenshots. 

 

 

We have gone through the 35.6.3.2 Preloading of the Slave Shift Register section in the datasheet and set the CTRLB.PLOADEN and verified the communication. Still, there is no success.

We read the bit and confirmed that it is set. 

 

Please explain to us what we need to do exactly for SPI write. Anything we are missing? 

 

 

Jana8153

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

We have one more observation. We have hardcoded 0x64 (decimal 100) in firmware and add this value to received byte from master. 

 

For example, 

 

master sends 0x01 and slave should send 101 (0x65)
master sends 0x02 and slave should send 102 (0x66)

 

We have sent dummy byte as 0x00 after sending an actual byte to slave. At that time, we are getting expected values in dummy byte result. Please refer the attached screenshot. 

 

Do we need to send dummy byte for every transmission? then only we will get the actual value. 

 

Jana8153

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

Probably you need the dummy yes, it's as I mentioned how a command/response SPI transaction usually ends up looking

This is the reason a SPI transaction is often some command from the master and then the master is required to send dummy bytes to clock out the response from the slave.

/Lars 

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

Hi Lars,

Thanks for your reply,

 

If 200 us (micro secs) delay and dummy bytes include then it will affect our firmware performance. 

 

Because we want to read multiple ADC data. Any performance issue will come?

 

so for getting 1 actual data, I need to do (1 actual data + 1 dummy data) write operations.

 
 

Jana8153

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

I guess nothing prevents you from getting more than one ADC reading in each transaction. E.g., slave responds to the initial command with the number of available readings and the master clocks out all of them.

/Lars

 

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

Lajon wrote:

I guess nothing prevents you from getting more than one ADC reading in each transaction. E.g., slave responds to the initial command with the number of available readings and the master clocks out all of them.

/Lars

 

 

But we need to send dummy byte for each command byte. Is it correct? Whether it is an issue or SPI behavior.

 

Can you please explain this? How to read multiple bytes from slave by issuing one command byte? 

Jana8153

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

Since the slave can't respond to a command that it has not yet received you do need one dummy byte (the first proper response from the slave will be available when that dummy byte is completely sent). However this should not be a big overhead if your command is "send n ADC values" or similar, i.e., following the first dummy byte there can be more data sent in the same transaction (dummys from the master and useful data from the slave). The number of bytes to clock out from the slave must be part of the protocol (e.g., fixed based on the command, determined by some response from the slave or continuous while slave select is asserted).

/Lars