Author Topic: SAMC21: SPI receiving problem  (Read 1802 times)

0 Members and 1 Guest are viewing this topic.

Offline YipeeTopic starter

  • Contributor
  • Posts: 10
  • Country: cz
SAMC21: SPI receiving problem
« on: March 08, 2021, 02:02:48 pm »
Hello,

I am trying to receive SPI communication. I am using SAMC21 Xplained Pro board. I selected this MCU because the project should use two CAN interfaces but I'm stuck at the beggining. Also I'm begginer at MCU's.

I am able to receive data from Arduino Uno, but it requires delays between SS edges and between bytes. But when I connected it to real device it didn't worked. Then I tried to connect SERCOM1 as SPI slave and SERCOM5 as SPI master. I tested if I can receive data via SERCOM1 with the Arduino Uno (still with delays) and I connected oscilloscope to SERCOM5 to check if it is sending data. Both seems okay, but when I connect SERCOM5 to SERCOM1 the receiving does not work.

My code base is from ASF examples for polled SPI:
https://asf.microchip.com/docs/3.49.1/samc21/html/asfdoc_sam0_sercom_spi_slave_basic_use.html
https://asf.microchip.com/docs/3.49.1/samc21/html/asfdoc_sam0_sercom_spi_master_basic_use.html

Main loop:

Code: [Select]
while (1) {
if(!port_pin_get_input_level(BUTTON_0_PIN)) {
spi_select_slave(&spi_master_instance, &slave, true);
spi_write_buffer_wait(&spi_master_instance, buffer, SPI_BUF_LENGTH);
spi_select_slave(&spi_master_instance, &slave, false);
port_pin_set_output_level(LED_0_PIN, LED0_ACTIVE);
}

if (spi_read_buffer_wait(&spi_slave_instance, buffer_rx, SPI_BUF_LENGTH, 0x00) == STATUS_OK) {
uint8_t ok = true;
for(uint8_t i = 0; i < SPI_BUF_LENGTH; i++) {
ok &= buffer_rx[i] == buffer[i];
}

port_pin_set_output_level(LED_0_PIN, LED0_INACTIVE);
}
}

Slave mux settings:

Code: [Select]
#define CONF_SLAVE_SPI_MODULE SERCOM1
#define CONF_SLAVE_MUX_SETTING SPI_SIGNAL_MUX_SETTING_O
#define CONF_SLAVE_PINMUX_PAD0 PINMUX_PA16C_SERCOM1_PAD0
#define CONF_SLAVE_PINMUX_PAD1 PINMUX_PA17C_SERCOM1_PAD1
#define CONF_SLAVE_PINMUX_PAD2 PINMUX_PA18C_SERCOM1_PAD2
#define CONF_SLAVE_PINMUX_PAD3 PINMUX_PA19C_SERCOM1_PAD3

Master mux settings:

Code: [Select]
#define CONF_MASTER_SPI_MODULE SERCOM5
#define CONF_MASTER_MUX_SETTING SPI_SIGNAL_MUX_SETTING_E
#define CONF_MASTER_PINMUX_PAD0 PINMUX_PB02D_SERCOM5_PAD0
#define CONF_MASTER_PINMUX_PAD1 PINMUX_PB03D_SERCOM5_PAD1
#define CONF_MASTER_PINMUX_PAD2 PINMUX_PB00D_SERCOM5_PAD2
#define CONF_MASTER_PINMUX_PAD3 PINMUX_PB01D_SERCOM5_PAD3

Rest of code should be the same as examples.

I also tried to modify ASF SPI slave callback example but I received only one interrupt and then nothing - the program never ran to handler again. But I tested it only against Arduino Uno where the communication was working with SPI polling.

I don't need the master SPI, I use it now just for debug, if I can receive what I sent with no delays cheat, do you know what am I doing wrong? :-// Is it possible to send and receive data using one MCU without interrupts?

Now I am trying writing directly to registers, but I don't have it working yet.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11262
  • Country: us
    • Personal site
Re: SAMC21: SPI receiving problem
« Reply #1 on: March 08, 2021, 08:18:56 pm »
I don't fully understand your description. Your want a SPI slave and it works if you insert pauses between the bytes? How fast is your clock and how long of a pause you need to insert?
Alex
 

Offline oliviasmithh900

  • Contributor
  • !
  • Posts: 23
  • Country: us
Re: SAMC21: SPI receiving problem
« Reply #2 on: March 08, 2021, 10:54:56 pm »
Is it possible to send and receive data using one MCU without interrupts?

Yeah you can send data continuously via SPI Protocol .... that's why SPI is for  :box:
 
The following users thanked this post: Yipee

Offline YipeeTopic starter

  • Contributor
  • Posts: 10
  • Country: cz
Re: SAMC21: SPI receiving problem
« Reply #3 on: March 09, 2021, 09:53:26 am »
I don't fully understand your description. Your want a SPI slave and it works if you insert pauses between the bytes? How fast is your clock and how long of a pause you need to insert?

It requires 10µs long pause after SS LOW and before SS HIGH and 6µs between bytes. I haven't checked it by oscilloscope, but these are minimal values set to Arduino's function DelayMicroseconds. When I set lower values then it shifts order of bytes or could not read it at all.

I had set clock divider to three, so the frequency of SAMC21 should be 16MHz. With the pauses I could receive data up to baud 16Mbits, but without them it did not receive anything even if the baud was set to 100kbits.

Now I also noticed that when I set buffer length 2 or less then the loop from SERCOM5 to SERCOM1 works at full speed without delays. I even tested baud 24Mbits (with clock set to 48Mhz) and it works. Unfortunatelly I need to receive three bytes long value.  :-BROKE

Is it possible to send and receive data using one MCU without interrupts?

Yeah you can send data continuously via SPI Protocol .... that's why SPI is for  :box:

Thanks, but I meant the question if MCU can receive data on SPI1 which were sent from SPI5 by the same MCU without callbacks (using pooling only). I know I asked wrong question, my fault  :-X. But I already know the answer: it is possible. I thought it whole time, just my code was convincing me opposite.


Which register should I "kill" to receive at least 3 bytes long value as fast as possible?  :horse:
« Last Edit: March 09, 2021, 09:57:35 am by Yipee »
 

Offline YipeeTopic starter

  • Contributor
  • Posts: 10
  • Country: cz
Re: SAMC21: SPI receiving problem
« Reply #4 on: March 09, 2021, 03:50:14 pm »
I noticed that when the buffer size is bigger than two bytes then I am stil able to receive first two bytes. The RX buffer loads first two bytes with received data but the rest of the buffer is filled by zeroes.

But I think I solved the problem with callback version. When I called spi_read_buffer_job again after receiving data, then it seems working fast.  I thought that I tried this million times but maybe I had there another bug...

Thank you for your support. Now I'm just curious why only two bytes are fast when using the pooling. Do you have an idea?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11262
  • Country: us
    • Personal site
Re: SAMC21: SPI receiving problem
« Reply #5 on: March 09, 2021, 05:14:59 pm »
I had set clock divider to three, so the frequency of SAMC21 should be 16MHz. With the pauses I could receive data up to baud 16Mbits, but without them it did not receive anything even if the baud was set to 100kbits.
The drivers in ASF are highly inefficient. They should be able to receive at 100 kBits/s though. But if you want high performance, you would have to write high performance code. And you need to run at the fastest possible clock.

How fast you can receive 1 or 2 bytes is irrelevant, since this is done by the hardware. After that software needs to receive the buffered data.

So I'd say what you are observing is normal and if you want things to be fast, you need to write fast drivers. And for that you need to dispose of the ASF. You can leave the clock initialization stuff and all that, but you will have to write the SPI driver yourself.
Alex
 
The following users thanked this post: Yipee

Offline YipeeTopic starter

  • Contributor
  • Posts: 10
  • Country: cz
Re: SAMC21: SPI receiving problem
« Reply #6 on: March 11, 2021, 07:33:41 am »
So I'd say what you are observing is normal and if you want things to be fast, you need to write fast drivers. And for that you need to dispose of the ASF. You can leave the clock initialization stuff and all that, but you will have to write the SPI driver yourself.

Thank you for the answer. It is a wishlist item to write the drivers by myself but for now the ASF solution is good enough.
 

Offline YipeeTopic starter

  • Contributor
  • Posts: 10
  • Country: cz
Re: SAMC21: SPI receiving problem
« Reply #7 on: March 17, 2021, 11:18:44 am »
I am here again. The loop from SPI5 to SPI1 works like charm, but I tried to connect Arduino again (Arduino -> SPI1, SPI5 not connected). It reads few values then it stops reading. By "few values" I mean something between 0 and 200000. When Moon is in good conjunction with Mars then it can receive even more values.

To the problem: when it stops receiving, all SPI interrupt flags are set except error flag. The error flag can be set too, but it is not a rule. I have callback for SPI_CALLBACK_BUFFER_RECEIVED, but it is not called an more - transfer_complete_spi_slave is false. When I call spi_abort_job and then register it again with spi_read_buffer_job, then an overflow error is raised.

What is the correct way to handle this situation? I tried a lot of things (even init the spi again), but when it stops reading I couldn't get it working again. I know, the best solution would be to write own spi driver, but there is no time for it now.
 

Offline YipeeTopic starter

  • Contributor
  • Posts: 10
  • Country: cz
Re: SAMC21: SPI receiving problem
« Reply #8 on: March 17, 2021, 03:39:28 pm »
To the problem: when it stops receiving, all SPI interrupt flags are set except error flag. The error flag can be set too, but it is not a rule. I have callback for SPI_CALLBACK_BUFFER_RECEIVED, but it is not called an more - transfer_complete_spi_slave is false. When I call spi_abort_job and then register it again with spi_read_buffer_job, then an overflow error is raised.

What is the correct way to handle this situation? I tried a lot of things (even init the spi again), but when it stops reading I couldn't get it working again. I know, the best solution would be to write own spi driver, but there is no time for it now.

I solved it by using DMA.  :phew: I don't know if the problem appears again, but it seems a lot better now.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf