Skip to content

SERCOM::initSPI() Prevents Hardware Control of SPI SS Signal by Clearing SERCOM_SPI_CTRLB_MSSEN #283

Open
@Rymar-Eng

Description

@Rymar-Eng

In cores/SERCOM.cpp, the SPI init function SERCOM::initSPI completely overwrites the value of the CTRLB register:

...
  //Setting the CTRLB register
  sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(charSize) |
                          SERCOM_SPI_CTRLB_RXEN; //Active the SPI receiver.
...

In order to support hardware control of the SPI SS output, the MSSEN bit must be set in the CTRLB register. For example, on the Grand Central M4 board (SAMD51), pin 53 ('SS' signal) will be driven as a hardware controlled SS pin if the MSSEN bit is set in the corresponding SERCOM controller, in this case SERCOM7.

SERCOM7->SPI.CTRLB.reg|= SERCOM_SPI_CTRLB_MSSEN`

However, each call to SERCOM::InitSPI() as a result of the call to SPI.beginTransaction() clears the MSSEN bit, and leaves pin 53 disconnected.

One method (perhaps not the best one), is to preserve the existing state in the register. This must be done before the call to resetSPI(), which clears all the internal register, including CTRLB.

The completed function looks like this

void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder)
{
  uint32_t ctrlb_image = sercom->SPI.CTRLB.reg;
  resetSPI();
  initClockNVIC();

#if defined(__SAMD51__)
  sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(0x3)  |  // master mode
                          SERCOM_SPI_CTRLA_DOPO(mosi) |
                          SERCOM_SPI_CTRLA_DIPO(miso) |
                          dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
#else
  //Setting the CTRLA register
  sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
                          SERCOM_SPI_CTRLA_DOPO(mosi) |
                          SERCOM_SPI_CTRLA_DIPO(miso) |
                          dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
#endif

  //Setting the CTRLB register
  sercom->SPI.CTRLB.reg = (ctrlb_image & SERCOM_SPI_CTRLB_MSSEN) |
                          SERCOM_SPI_CTRLB_CHSIZE(charSize) |
                          SERCOM_SPI_CTRLB_RXEN; //Active the SPI receiver.

  while( sercom->SPI.SYNCBUSY.bit.CTRLB == 1 );
}

An explicit parameter could also be used to pass in the value in, but would affect higher layers of the SPI interface.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions