I am attempting to use an M0 as an SPI slave on the default SPI bus (SERCOM4). I believe that all the registers are being set correctly, but when I set the enable register with this line, the program freezes:
SERCOM4->SPI.CTRLA.bit.ENABLE = 0x1;
I've also tried it like this:
REG_SERCOM4_SPI_CTRLA |= (1 << 1);
Any ideas why writing to this register might be causing it to freeze? Also, if you know an easier way to get the M0 to work as an SPI slave, I'm open to suggestions. Thanks.
Here is the full setup code:
void SPI_Slave_Setup()
{
SerialUSB.println("Entering Slave Setup");
// Enable Peripheral Multiplexing for SERCOM4 SPI
PORT->Group[PORTB].PINCFG[9].bit.PMUXEN = 0x1; // SS on PB09 (SERCOM4.1 ALT)
PORT->Group[PORTB].PINCFG[10].bit.PMUXEN = 0x1; // MOSI on PB10 (SERCOM4.2 ALT)
PORT->Group[PORTB].PINCFG[11].bit.PMUXEN = 0x1; // SCK on PB11 (SERCOM4.3 ALT)
PORT->Group[PORTA].PINCFG[12].bit.PMUXEN = 0x1; // MISO on PA12 (SERCOM4.0 ALT)
// Setup MUX for peripheral use of this pad. 0x3 selects ALT pad
PORT->Group[PORTB].PMUX[4].bit.PMUXO = 0x3; // Odd mux rounddown(pin#/2)
PORT->Group[PORTB].PMUX[5].bit.PMUXE = 0x3; // Even mux rounddown(pin#/2)
PORT->Group[PORTB].PMUX[5].bit.PMUXO = 0x3;
PORT->Group[PORTA].PMUX[6].bit.PMUXE = 0x3;
//Disable SPI
SERCOM4->SPI.CTRLA.bit.ENABLE = 0;
while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
//Reset SPI
SERCOM4->SPI.CTRLA.bit.SWRST = 1;
while(SERCOM4->SPI.CTRLA.bit.SWRST || SERCOM4->SPI.SYNCBUSY.bit.SWRST);
//Setting up NVIC
NVIC_EnableIRQ(SERCOM4_IRQn);
NVIC_SetPriority(SERCOM4_IRQn,2);
//Setting Generic Clock Controller
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_SERCOM4_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 synchronization
//Set up SPI Control A Register
SERCOM4->SPI.CTRLA.bit.DORD = 0; // MSB first
SERCOM4->SPI.CTRLA.bit.CPOL = 0; // SCK is low when idle, leading edge is rising edge
SERCOM4->SPI.CTRLA.bit.CPHA = 0; // data sampled on leading sck edge and changed on a trailing sck edge
SERCOM4->SPI.CTRLA.bit.FORM = 0x0; // Frame format = SPI
SERCOM4->SPI.CTRLA.bit.DIPO = 0x2; // PAD[2]: MOSI
SERCOM4->SPI.CTRLA.bit.DOPO = 0x3; // PAD[0]: MISO , PAD[3]: SCK, PAD[1]: SS
SERCOM4->SPI.CTRLA.bit.MODE = 0x2; // SPI in Slave mode
SERCOM4->SPI.CTRLA.bit.IBON = 0x1; // Buffer Overflow notification
SERCOM4->SPI.CTRLA.bit.RUNSTDBY = 1; // wake on receiver complete
//Set up SPI control B register
SERCOM4->SPI.CTRLB.bit.SSDE = 0x1; //Slave Select Detection Enabled
SERCOM4->SPI.CTRLB.bit.CHSIZE = 0; //character size 8 Bit
//SERCOM4->SPI.CTRLB.bit.PLOADEN = 0x1; //Enable Preload Data Register
//Set up SPI interrupts
SERCOM4->SPI.INTENSET.bit.SSL = 0x1; //Enable Slave Select low interrupt
SERCOM4->SPI.INTENSET.bit.RXC = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.TXC = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.ERROR = 0x1; //Receive complete interrupt
SERCOM4->SPI.INTENSET.bit.DRE = 0x1; //Data Register Empty interrupt
//init SPI CLK
//SERCOM4->SPI.BAUD.reg = SERCOM_FREQ_REF / (2*4000000u)-1;
//Enable SPI
SERCOM4->SPI.CTRLA.bit.ENABLE = 0x1; // <<<<<<<<<<<< Causes code to freeze
while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE);
SERCOM4->SPI.CTRLB.bit.RXEN = 0x1; //Enable Receiver, this is done here due to errate issue
while(SERCOM4->SPI.SYNCBUSY.bit.CTRLB); //wait until receiver is enabled
SerialUSB.println("SPI Setup Complete");
}
Thanks Matthew, I will try it for SERCOM1 too, trying to connect a SAMD21 and a Pi Zero.
Actually I already solved it some time ago but forgot about it:
My latest problem was that I had a CS0 / CS1 option on my board and incorrectly soldered it to CS1 setting thinking it was the CS0 jumper between SAMD21 and Pi. After putting a Analog Discovery 2 from Digilent to the SPI pins I realized the signal came correctly from both sides but the SAMD21 did not detect the changes for it's SS and did not issue interrupts.
I actually also got the Python script working now.
I desperately need help to Slave 2 SAMD21 chips. I am new in general to slaving 2 Micro-controller.
MatthewHoworko has posted code to SPI Slave a SAMD21 board but I still cant get it to work.
At the bottom of the code MatthewHoworko posted there is a void SERCOM4_Handler(void) but its never called, so maybe that is my problem
I have been looking everywhere on how to slave one SAMD21 to another with no successes. Apparently a lot of other people have the same problem.
What is promising is jopiek was able to use this code to slave to a Pi
I continued to work on it and can get it to work with jopiek's Slave code and no SERCOM editing on the Master!!!!!!!!!! Thank you jopiek
Although i dont know what the Bit Shifting is for, at-least it works