This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SPI hanging up

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

Parents
  • 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.

Reply
  • 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.

Children