SPI Receiver Fails to Enable with SYNCBUSY.CTRLB Stuck High

The issue at hand involves the SPI receiver on an ATSAMD21G18A (Cortex-M0) microcontroller failing to enable, with the SYNCBUSY.CTRLB bit persistently set to one. This prevents the receiver from being enabled, as indicated by the CTRLB.RXEN bit not being set correctly. The problem manifests after enabling the SPI module, and the root cause appears to be related to improper configuration of the SPI control registers, particularly the CTRLA register. The SYNCBUSY mechanism, which ensures proper synchronization of register updates, is not being handled correctly, leading to a deadlock state where the receiver cannot be enabled.

The SPI module on the ATSAMD21G18A relies on a series of synchronization steps to ensure that configuration changes are applied safely. When the SPI is enabled, the SYNCBUSY.CTRLB bit is set, indicating that the CTRLB register is being updated. The receiver enable bit (CTRLB.RXEN) should be set only after this synchronization is complete. However, in this case, the SYNCBUSY.CTRLB bit remains high, suggesting that the synchronization process is being interrupted or improperly handled.

The provided code snippet shows that the SPI module is being configured in several steps, including setting the clock, performing a software reset, and configuring the CTRLA and CTRLB registers. However, a critical mistake is made when the CTRLA register is overwritten after initial configuration, which inadvertently resets some of the previously set fields, including the mode and pad settings. This overwrite disrupts the synchronization process and prevents the receiver from being enabled.

CTRLA Register Overwrite and Improper Synchronization Handling

The primary cause of the issue is the improper handling of the CTRLA register, specifically the overwrite of the register after initial configuration. The CTRLA register controls the fundamental operation of the SPI module, including the mode, clock polarity, clock phase, and data order. When the CTRLA register is written to, the hardware initiates a synchronization process to apply the changes. This process is indicated by the SYNCBUSY bit being set.

In the provided code, the CTRLA register is initially configured with the desired settings, including the mode (master operation), data order, clock polarity, and clock phase. However, the register is later overwritten with a new value that includes the SERCOM_SPI_CTRLA_FORM(0) field. This overwrite resets the mode and pad settings, effectively undoing the previous configuration. The mode field, which must be set to either 2 or 3 for SPI master operation, is reset to 0, rendering the SPI module inoperable.

Additionally, the synchronization process is not being handled correctly. The SYNCBUSY bit must be checked after each register write to ensure that the changes have been applied before proceeding to the next step. In the provided code, while there are checks for SYNCBUSY after some operations, they are not consistently applied, leading to potential race conditions and incomplete synchronization. This is particularly problematic when enabling the receiver, as the SYNCBUSY.CTRLB bit must be clear before setting the CTRLB.RXEN bit.

Another potential cause is the improper handling of the software reset (SWRST) process. The SWRST bit is used to reset the SPI module to its default state. However, the synchronization process for the SWRST operation is not being handled correctly. The SYNCBUSY.SWRST bit must be checked both before and after setting the SWRST bit to ensure that the reset operation is complete before proceeding with further configuration.

Correcting CTRLA Configuration and Ensuring Proper Synchronization

To resolve the issue, the following steps should be taken to ensure proper configuration of the SPI module and correct handling of the synchronization process:

  1. Avoid Overwriting the CTRLA Register: The CTRLA register should be configured in a single write operation, including all necessary fields such as mode, data order, clock polarity, and clock phase. This prevents the register from being inadvertently reset and ensures that all settings are applied correctly. For example:

    SERCOM4->SPI.CTRLA.reg = pad_conf | SERCOM_SPI_CTRLA_MODE(3) | SERCOM_SPI_CTRLA_DORD(0) | SERCOM_SPI_CTRLA_CPOL(0) | SERCOM_SPI_CTRLA_CPHA(0);
    
  2. Proper Handling of Synchronization: After each register write that triggers a synchronization process, the SYNCBUSY bit must be checked to ensure that the operation is complete before proceeding. This includes writes to the CTRLA, CTRLB, and BAUD registers, as well as the SWRST and ENABLE bits. For example:

    while (SERCOM4->SPI.SYNCBUSY.reg & SERCOM_SPI_SYNCBUSY_CTRLA);
    
  3. Correct Sequence for SPI Configuration: The SPI module should be configured in the following sequence to ensure proper operation:

    • Perform a software reset (SWRST) and wait for synchronization.
    • Set the baud rate (BAUD.reg) and wait for synchronization.
    • Configure the CTRLA register in a single write operation and wait for synchronization.
    • Enable the receiver by setting the CTRLB.RXEN bit and wait for synchronization.
    • Enable the SPI module by setting the CTRLA.ENABLE bit and wait for synchronization.
  4. Example Code Implementation:

    /* Enable clock for SPI */
    PM->APBCMASK.reg |= SPI_BUS_CLOCK_INDEX;
    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM4_GCLK_ID_CORE) | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN;
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
    
    /* Perform a software reset */
    SERCOM4->SPI.CTRLA.bit.SWRST = 1;
    while (SERCOM4->SPI.SYNCBUSY.reg & SERCOM_SPI_SYNCBUSY_SWRST);
    
    /* Set baud rate */
    SERCOM4->SPI.BAUD.reg = 250;
    while (SERCOM4->SPI.SYNCBUSY.reg & SERCOM_SPI_SYNCBUSY_BAUD);
    
    /* Configure CTRLA register */
    SERCOM4->SPI.CTRLA.reg = pad_conf | SERCOM_SPI_CTRLA_MODE(3) | SERCOM_SPI_CTRLA_DORD(0) | SERCOM_SPI_CTRLA_CPOL(0) | SERCOM_SPI_CTRLA_CPHA(0);
    while (SERCOM4->SPI.SYNCBUSY.reg & SERCOM_SPI_SYNCBUSY_CTRLA);
    
    /* Enable receiver */
    SERCOM4->SPI.CTRLB.bit.RXEN = 1;
    while (SERCOM4->SPI.SYNCBUSY.reg & SERCOM_SPI_SYNCBUSY_CTRLB);
    
    /* Enable SPI module */
    SERCOM4->SPI.CTRLA.bit.ENABLE = 1;
    while (SERCOM4->SPI.SYNCBUSY.reg & SERCOM_SPI_SYNCBUSY_ENABLE);
    

By following these steps, the SPI module should be correctly configured, and the receiver should be enabled without encountering synchronization issues. Proper handling of the CTRLA register and synchronization process is critical to ensuring reliable operation of the SPI module on the ATSAMD21G18A microcontroller.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *