Hello!
I am trying to use SPI between my ATSAMD21G18A (Cortex M0) as master and a radio module as slave. I am able to initiate the SPI, but having trouble enabling the receiver (RXEN). The manual states:
Writing a one to CTRLB.RXEN when the SPI is disabled will set CTRLB.RXEN immediately. When the SPI is enabled, CTRLB.RXEN will be cleared, SYNCBUSY.CTRLB will be set and remain set until the receiver is enabled. When the receiver is enabled CTRLB.RXEN will read back as one.
After enabling the SPI, SYNCBUSY.CTRLB is always set to one and the receiver is not being enabled.
My suspicion is that I'm wrongly configuring the clocks for the SPI. Here is the code below for the clocks and SPI configuration I have.
/* Enable clock for SPI */ PM->APBCMASK.reg |= SPI_BUS_CLOCK_INDEX; GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM4_GCLK_ID_CORE) | // Generic Clock for SERCOM4 GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source GCLK_CLKCTRL_CLKEN; while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } /* Wait for synchronization */ while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE); /* Disable the SERCOM SPI module */ SERCOM4->SPI.CTRLA.bit.ENABLE = 0; /* Wait for synchronization */ while(SERCOM4->SPI.SYNCBUSY.bit.SWRST); /* Perform a software reset */ SERCOM4->SPI.CTRLA.bit.SWRST = 1; /* Wait for synchronization */ while(SERCOM4->SPI.CTRLA.bit.SWRST); /* Wait for synchronization */ while(SERCOM4->SPI.SYNCBUSY.bit.SWRST || SERCOM4->SPI.SYNCBUSY.bit.ENABLE); /* Update the SPI pad settings, mode and data order settings */ SERCOM4->SPI.CTRLA.reg = pad_conf | SERCOM_SPI_CTRLA_MODE(3); //SPI in master operation (0x3) SERCOM4->SPI.CTRLA.bit.DORD = 0; //Data order MSB first SERCOM4->SPI.CTRLA.bit.CPOL = 0; //Clock polarity SERCOM4->SPI.CTRLA.bit.CPHA = 0; //Clock phase SERCOM4->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_FORM(0); //format while(SERCOM4->SPI.SYNCBUSY.bit.CTRLB); SERCOM4->SPI.CTRLB.bit.RXEN = 1; uint8_t baud_val = 250; SERCOM4->SPI.BAUD.reg = baud_val; /* Wait for synchronization */ while(SERCOM4->SPI.SYNCBUSY.bit.ENABLE); /* Enable SERCOM SPI */ SERCOM4->SPI.CTRLA.bit.ENABLE = 1; while(SERCOM4->SPI.SYNCBUSY.reg & SERCOM_SPI_SYNCBUSY_ENABLE);
Any help is appreciated!
Best regards,
Barry
SERCOM4->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_FORM(0); //format
This line is overwritting the CTRLA register value PAD's and Mode are overwritten. (Mode must be 2 or 3, but it will now be 0)
This might be the only issue. I usually just do the following 4 steps (assuming CCLK proper and assigned for SERCOM and device enabled)
SWRTS // SyncBusy SWRST before and after (Can do SyncBusy (SWRST & ENABLE) after just in case)
BAUD.reg = Your_BAUD
CTRLA.reg = Entire Register at once including enable // SyncBusy ENABLE before and after
CTRLB.reg = Entire Register (may just be RX_Enable) // SyncBusy CTRLB before and after
Should be enabled here.
Thank you Robert! You're a life saver :)