Go Down

Topic: Arduino Zero Sercom1 SPI Slave (Read 3902 times) previous topic - next topic

Tom_the_banana

I have problems getting the SPI Slave to work in the Sercom1 module. SPI Master is another Arduino Zero. I measured the transmission lines (SCK, MISO, MOSI, SS) with an oscilloscope where I see that data is correctly transmitted. I use SPI mode 0 and send an character (0xAA).

What works:
- Data transmission (oscilloscope measurement) correct
- I get interrupts on slave select low, high and receive register empty(SSL, TXC and DRE Interrupt)

What doesn't work:
- I don't get a Data received interrupt (RXC)
- the data register is empty

What I tried:
-measured with an oscilloscope
-checking different SPI modes
-reading the configured registers to check if the initialisation where done correctly
-reading the datasheet multiple times for any hints. especially page 484



Here is my initialisation code for the spi module:

Code: [Select]
void spiSlave_init()
{

//Configure SERCOM1 SPI PINS
PORTA.DIR.reg &= ~PORT_PA16; //Set PA16 as input (MOSI)
PORTA.DIR.reg &= ~PORT_PA17; //Set PA17 as input (SCK)
PORTA.DIR.reg &= ~PORT_PA18; //Set PA18 as input (SS)
PORTA.DIR.reg |= PORT_PA19; //Set PA19 as output (MISO)


PORTA.PINCFG[16].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORTA.PMUX[0].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORTA.PINCFG[17].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORTA.PMUX[0].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORTA.PINCFG[18].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORTA.PMUX[9].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORTA.PINCFG[19].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORTA.PMUX[9].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad


//Disable SPI 1
SERCOM1->SPI.CTRLA.bit.ENABLE =0;
while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);

//Reset SPI 1
SERCOM1->SPI.CTRLA.bit.SWRST = 1;
while(SERCOM1->SPI.CTRLA.bit.SWRST || SERCOM1->SPI.SYNCBUSY.bit.SWRST);

//Setting up NVIC
NVIC_EnableIRQ(SERCOM1_IRQn);
NVIC_SetPriority(SERCOM1_IRQn,2);

//Setting Generic Clock Controller!!!!
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM1_CORE) | //Generic Clock 0
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is the source
GCLK_CLKCTRL_CLKEN; // Enable Generic Clock Generator

while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); //Wait for synchronisation


//Set up SPI Control A Register
SERCOM1->SPI.CTRLA.bit.DORD = 0; //MSB first
SERCOM1->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
SERCOM1->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
SERCOM1->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
SERCOM1->SPI.CTRLA.bit.DIPO = 0; //DATA PAD0 MOSI is used as input (slave mode)
SERCOM1->SPI.CTRLA.bit.DOPO = 0x2; //DATA PAD3 MISO is used as output
SERCOM1->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
SERCOM1->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
SERCOM1->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete

//Set up SPI control B register
//SERCOM1->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
SERCOM1->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
SERCOM1->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
//SERCOM1->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
//while (SERCOM1->SPI.SYNCBUSY.bit.CTRLB);

//Set up SPI interrupts
SERCOM1->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt
SERCOM1->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
SERCOM1->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
SERCOM1->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
SERCOM1->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
//init SPI CLK
//SERCOM1->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
//Enable SPI
SERCOM1->SPI.CTRLA.bit.ENABLE = 1;
while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);
SERCOM1->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
while(SERCOM1->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled

}


Any ideas or hints?

Tom_the_banana

#1
Nov 17, 2015, 12:13 pm Last Edit: Nov 17, 2015, 12:47 pm by Tom_the_banana
okay just by posting this my brain went out of filtering my code mode, to look at your code correctly mode :-)

I found the issue right away the problem was in the pinmux section, i didnt initialise MISO and SCK correctly. Here is my working example code with interrupt handler. You can use it for the Arduino Zero/Zero Pro to use Pin 10,11,12,13 (SS, MOSI, MISO, SCK)as SPI in slave mode. Have fun!

Interrupt Service Routine:
Code: [Select]
void SERCOM1_Handler()
{
Serial.println("In SPI Interrupt");
uint8_t data = 0;
data =(uint8_t)SERCOM1->SPI.DATA.reg;
uint8_t interrupts = SERCOM1->SPI.INTFLAG.reg; //Read SPI interrupt register
Serial.println(interrupts);
if(interrupts & (1<<3))
{
Serial.println("SPI SSL Interupt");
SERCOM1->SPI.INTFLAG.bit.SSL = 1; //clear slave select interrupt
}
if(interrupts & (1<<2))
{
Serial.println("SPI Data Received Complete Interrupt");
data = SERCOM1->SPI.DATA.reg; //Read data register
Serial.print("DATA: "); Serial.println(data);
SERCOM1->SPI.INTFLAG.bit.RXC = 1; //clear receive complete interrupt
}
if(interrupts & (1<<1))
{
Serial.println("SPI Data Transmit Complete Interrupt");
SERCOM1->SPI.INTFLAG.bit.TXC = 1; //clear receive complete interrupt
}

if(interrupts & (1<<0))
{
Serial.println("SPI Data Register Empty Interrupt");
SERCOM1->SPI.DATA.reg = 0xAA;
}
Serial.print("DATA: "); Serial.println(data);
//Serial.print("CTRLA: "); Serial.println(SERCOM1->SPI.CTRLA.reg);
}




SPI init function:
Code: [Select]
void spiSlave_init()
{

//Configure SERCOM1 SPI PINS
PORTA.DIR.reg &= ~PORT_PA16; //Set PA16 as input (MOSI)
PORTA.DIR.reg &= ~PORT_PA17; //Set PA17 as input (SCK)
PORTA.DIR.reg &= ~PORT_PA18; //Set PA18 as input (SS)
PORTA.DIR.reg |= PORT_PA19; //Set PA19 as output (MISO)


PORTA.PINCFG[16].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORTA.PMUX[8].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORTA.PINCFG[17].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORTA.PMUX[8].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORTA.PINCFG[18].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORTA.PMUX[9].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORTA.PINCFG[19].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORTA.PMUX[9].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad


//Disable SPI 1
SERCOM1->SPI.CTRLA.bit.ENABLE =0;
while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);

//Reset SPI 1
SERCOM1->SPI.CTRLA.bit.SWRST = 1;
while(SERCOM1->SPI.CTRLA.bit.SWRST || SERCOM1->SPI.SYNCBUSY.bit.SWRST);

//Setting up NVIC
NVIC_EnableIRQ(SERCOM1_IRQn);
NVIC_SetPriority(SERCOM1_IRQn,2);

//Setting Generic Clock Controller!!!!
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM1_CORE) | //Generic Clock 0
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is the source
GCLK_CLKCTRL_CLKEN; // Enable Generic Clock Generator

while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); //Wait for synchronisation


//Set up SPI Control A Register
SERCOM1->SPI.CTRLA.bit.DORD = 0; //MSB first
SERCOM1->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
SERCOM1->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
SERCOM1->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
SERCOM1->SPI.CTRLA.bit.DIPO = 0; //DATA PAD0 MOSI is used as input (slave mode)
SERCOM1->SPI.CTRLA.bit.DOPO = 0x2; //DATA PAD3 MISO is used as output
SERCOM1->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
SERCOM1->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
SERCOM1->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete

//Set up SPI control B register
//SERCOM1->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
SERCOM1->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
SERCOM1->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
//SERCOM1->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
//while (SERCOM1->SPI.SYNCBUSY.bit.CTRLB);

//Set up SPI interrupts
SERCOM1->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt
SERCOM1->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
SERCOM1->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
SERCOM1->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
SERCOM1->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
//init SPI CLK
//SERCOM1->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
//Enable SPI
SERCOM1->SPI.CTRLA.bit.ENABLE = 1;
while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);
SERCOM1->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
while(SERCOM1->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled

}



AloyseTech

Hi,

Thanks for sharing your code ! :)

Do you have the code for the master on pin 10,11,12,13 (SS, MOSI, MISO, SCK) as well ?

Tom_the_banana

I have to change a few register bits. I will do this in the next few days and then test if it works. I will post it afterwards. :-)

AloyseTech


s3by

#5
Apr 15, 2016, 12:29 pm Last Edit: Apr 15, 2016, 01:35 pm by s3by
Tom_the_banana - Thank you for posting, I am trying to do something very similar and was completely stuck until I came across this.

AloyseTech - There is a good explanation of how you can setup the master here:

https://learn.adafruit.com/using-atsamd21-sercom-to-add-more-spi-i2c-serial-ports/creating-a-new-spi

Scotty454

I am trying to use Tom_the_banana's SPI Slave code on an Adafruit Feather M0 with the 1.6.7 IDE and getting multiple identical compile errors -   

error: request for member 'DIR' in 'PORTA', which is of non-class type '_EPortType'

On the following lines of code in SPI init function:

PORTA.DIR.reg &= ~PORT_PA16; //Set PA16 as input (MOSI)
.
.
.
PORTA.PMUX[9].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad

Here's the full code listing:
Code: [Select]

#include <SPI.h>

const int slaveAPin = 10;

void setup() {

  Serial.begin(9600);

  pinMode(slaveAPin, INPUT_PULLUP);

  attachInterrupt(10, SERCOM1_Handler, FALLING);

  spiSlave_init();

}

void loop() {
  //waste some time in a loop
  int var = 0;
  while(var < 200){
  var++;
  }

}


void spiSlave_init()
{
 
  //Configure SERCOM1 SPI PINS
  PORTA.DIR.reg &= ~PORT_PA16; //Set PA16 as input (MOSI)
  PORTA.DIR.reg &= ~PORT_PA17; //Set PA17 as input (SCK)
  PORTA.DIR.reg &= ~PORT_PA18; //Set PA18 as input (SS)
  PORTA.DIR.reg |= PORT_PA19; //Set PA19 as output (MISO)

 
  PORTA.PINCFG[16].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORTA.PMUX[8].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORTA.PINCFG[17].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORTA.PMUX[8].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORTA.PINCFG[18].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORTA.PMUX[9].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
  PORTA.PINCFG[19].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
  PORTA.PMUX[9].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
 
 
  //Disable SPI 1
  SERCOM1->SPI.CTRLA.bit.ENABLE =0;
  while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);
 
  //Reset SPI 1
  SERCOM1->SPI.CTRLA.bit.SWRST = 1;
  while(SERCOM1->SPI.CTRLA.bit.SWRST || SERCOM1->SPI.SYNCBUSY.bit.SWRST);
 
  //Setting up NVIC
  NVIC_EnableIRQ(SERCOM1_IRQn);
  NVIC_SetPriority(SERCOM1_IRQn,2);
 
  //Setting Generic Clock Controller!!!!
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM1_CORE) | //Generic Clock 0
            GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is the source
            GCLK_CLKCTRL_CLKEN; // Enable Generic Clock Generator
 
  while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); //Wait for synchronisation
 
 
  //Set up SPI Control A Register
  SERCOM1->SPI.CTRLA.bit.DORD = 0; //MSB first
  SERCOM1->SPI.CTRLA.bit.CPOL = 0; //SCK is low when idle, leading edge is rising edge
  SERCOM1->SPI.CTRLA.bit.CPHA = 0; //data sampled on leading sck edge and changed on a trailing sck edge
  SERCOM1->SPI.CTRLA.bit.FORM = 0x0; //Frame format = SPI
  SERCOM1->SPI.CTRLA.bit.DIPO = 0; //DATA PAD0 MOSI is used as input (slave mode)
  SERCOM1->SPI.CTRLA.bit.DOPO = 0x2; //DATA PAD3 MISO is used as output
  SERCOM1->SPI.CTRLA.bit.MODE = 0x2; //SPI in Slave mode
  SERCOM1->SPI.CTRLA.bit.IBON = 0x1; //Buffer Overflow notification
  SERCOM1->SPI.CTRLA.bit.RUNSTDBY = 1; //wake on receiver complete
 
  //Set up SPI control B register
  //SERCOM1->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver
  SERCOM1->SPI.CTRLB.bit.SSDE = 0x1; //Slave Selecte Detection Enabled
  SERCOM1->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
  //SERCOM1->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
  //while (SERCOM1->SPI.SYNCBUSY.bit.CTRLB); 
 
  //Set up SPI interrupts
  SERCOM1->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt       
  SERCOM1->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
  SERCOM1->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
  SERCOM1->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
  SERCOM1->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
  //init SPI CLK 
  //SERCOM1->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
  //Enable SPI
  SERCOM1->SPI.CTRLA.bit.ENABLE = 1;
  while(SERCOM1->SPI.SYNCBUSY.bit.ENABLE);
  SERCOM1->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
  while(SERCOM1->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled

}


void SERCOM1_Handler()
{
  Serial.println("In SPI Interrupt");
  uint8_t data = 0;
  data =(uint8_t)SERCOM1->SPI.DATA.reg;
  uint8_t interrupts = SERCOM1->SPI.INTFLAG.reg; //Read SPI interrupt register
  Serial.println(interrupts);
  if(interrupts & (1<<3))
  {
    Serial.println("SPI SSL Interupt");
    SERCOM1->SPI.INTFLAG.bit.SSL = 1; //clear slave select interrupt
  }
  if(interrupts & (1<<2))
  {
    Serial.println("SPI Data Received Complete Interrupt");
    data = SERCOM1->SPI.DATA.reg; //Read data register
    Serial.print("DATA: "); Serial.println(data);
    SERCOM1->SPI.INTFLAG.bit.RXC = 1; //clear receive complete interrupt
  }
  if(interrupts & (1<<1))
  {
    Serial.println("SPI Data Transmit Complete Interrupt");
    SERCOM1->SPI.INTFLAG.bit.TXC = 1; //clear receive complete interrupt
  }
 
  if(interrupts & (1<<0))
  {
    Serial.println("SPI Data Register Empty Interrupt");
    SERCOM1->SPI.DATA.reg = 0xAA;
  }
  Serial.print("DATA: "); Serial.println(data);
  //Serial.print("CTRLA: "); Serial.println(SERCOM1->SPI.CTRLA.reg); 
}


I've searched Google and the forum posts without success.  I suspect there I'm missing a header file but not sure.  Any help or input would be appreciated.

MartinL

#7
May 26, 2016, 10:05 am Last Edit: May 26, 2016, 10:42 am by MartinL
Hi Scotty454,

First of all you don't need the lines:

Code: [Select]
//Configure SERCOM1 SPI PINS
PORTA.DIR.reg &= ~PORT_PA16; //Set PA16 as input (MOSI)
PORTA.DIR.reg &= ~PORT_PA17; //Set PA17 as input (SCK)
PORTA.DIR.reg &= ~PORT_PA18; //Set PA18 as input (SS)
PORTA.DIR.reg |= PORT_PA19; //Set PA19 as output (MISO)

This sets/clears bits in port A's data direction (DIR) register, but as the code is subsequently switching these pins over the SERCOM1, setting GPIO data direction is unnecessary.

Regarding the syntax, there are probably several ways, but I know the following works:

Code: [Select]
PORT->Group[PORTA].PINCFG[16].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORT->Group[PORTA].PMUX[8].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORT->Group[PORTA].PINCFG[17].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORT->Group[PORTA].PMUX[8].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORT->Group[PORTA].PINCFG[18].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORT->Group[PORTA].PMUX[9].bit.PMUXE = 0x2; //SERCOM 1 is selected for peripherial use of this pad
PORT->Group[PORTA].PINCFG[19].bit.PMUXEN = 0x1; //Enable Peripheral Multiplexing for SERCOM1 SPI PA18 Arduino PIN10
PORT->Group[PORTA].PMUX[9].bit.PMUXO = 0x2; //SERCOM 1 is selected for peripherial use of this pad

Scotty454

MartinL,

Thanks for explanation on the redundant GPIO setup and the syntax changes.  The code complies and runs now without errors after these changes.  I've learned a lot from your other posts and threads in the Zero forum!



Maverick123

#9
Oct 31, 2016, 10:07 pm Last Edit: Oct 31, 2016, 10:20 pm by Maverick123
Hi MartinL,

I have been trying to set the Feather M0 up as an SPI slave, using SCK (PB11), MOSI (PB10) and MISO (PA12). Attached is some code by Nick Gammon, appearing to work on boards based on ATmega328 chips. However lines

Code: [Select]
SPCR |= _BV(SPE);
ISR (SPI_STC_vect)


don't seem to work on the M0.

Could you help me to figure out how to use the M0 as an SPI slave? Should I use code similar to SercomSPI.ino with different pin numbers?

MartinL

#10
Nov 01, 2016, 11:04 am Last Edit: Nov 01, 2016, 11:04 am by MartinL
Hi Maverick123,

Unfortunately, I don't have experience of using the SAMD21 as a SPI slave.

Maverick123

#11
Nov 01, 2016, 12:10 pm Last Edit: Nov 01, 2016, 05:28 pm by Maverick123 Reason: New post
Hi MartinL,

thank you for your reply. I hope someone else could help me a bit further then. I will elaborate on my problem:
I am trying to connect two Adafruit Feather M0's  (SAMD21) to a Raspberry Pi 3B over SPI. One connected to the Raspberry's main SPI, the other to the Raspberry's auxiliary SPI. For this I am planning to use the pigpio-library on the Raspberry, which allows to use both the main and auxiliary SPI. Each Feather M0 should create 8 independent PWM signals. For setting up the PWM channels MartinL has helped me out in this thread:
Changing Arduino PWM Frequency - Page 8

Since I am not very experienced in programming for the Arduino, I have tried to adapt the file posted by Scotty454 to set the M0 up as an SPI slave. I would like to use the default SPI pins: PB11 (SCK), PB10 (MOSI), PA12 (MISO). Since I am using one SPI bus per Feather, I think I don't need to use a SS pin.

Maverick123

#12
Nov 01, 2016, 05:00 pm Last Edit: Nov 01, 2016, 05:10 pm by Maverick123
I have looked into it myself a bit more, and found out that I can use Sercom4 to create an SPI Slave. Sercom4 is also used by default for SPI, as can be found on this website

sercom: muxing-it-up

I have changed the code from Tom_the_banana  and Scotty454:
  • To use Sercom4 in stead of Sercom1.
  • Changed the port select from 0x2 to 0x3, to select the Sercom-alt

Code: [Select]
PORT->Group[PORTB].PMUX[5].bit.PMUXE = 0x3;
  • Changed DIPO to 2, to select PAD2 for MOSI (corresponding to PB10:MOSI on the board)
  • Changed DOPO to 0, to select PAD0 for MISO (corresponding to PA12:MISO on the board)
  • Defined slaveAPin = 16 (corresponding to PB09:A2 on the board), which is Sercom4 PAD1


Could someone give me some feedback? My Feather M0 hasn't arrived yet, so any feedback before that time would be very helpful. I will post the results of the test with the Feather M0 here once it has arrived.

hhbcd

I am new bee here. May I ask where do you find all these register setting?? And the programming style does not looks like arduino style. Where can I found any materiel about it? Thanks.



MartinL

Hi hhbcd,

On my Windows based machine the register definitions are located at:

C:\Users\Computer\AppData\Local\Arduino15\packages\tools\arduino\CMSIS\4.0.0-atmel\Device\ATMEL\samd21\include\

In the "include" directory, there are two further directories: "instance" and "component".

Instance contains the register definitions for each peripheral instance, for example tcc0.h, tcc1.h, etc...

Component contains the structures and definitions for the peripheral's register bitfields, for example tcc.h.

Go Up