Atmel Register Synchronization bits

May 10th 2018

For some of the peripherals in the Atmel Cortex processors, like the SAMD21 and SAMD20 there are some configuration registers that require synchronization.  Specifically these peripherals can run from a clock that is different speed than the processor clock to save power. For example run the UART Sercom clock at lower clock rate than processor to save power.  When a the processor changes a register value the peripheral will not see the change until it's clock has ticked to clock in the change. 

Normally this is not a problem, unless you try to write to the same register before the synchronization is done. When this does happen Atmel's data sheet says the second write is lost which can cause issues.  Therefore the best practice is to wait for the synchronization to complete before trying another write to same register/bit that requires synchronization. 

Atmel's datasheet can be difficult to understand when it comes to which bits and registers need to be synchronized. For example the Sercom I2C CTRL register:

It indicates that the register as a whole is Write-Synchronize at the top, however actually only some bits need synchronization.  Even then the datasheet does not always indicate which bits require synchronization, for example the LOWTOUT above has no information while the datasheet indicates the SDAHOLD is not synchronized. 

However in a section or two before the registers it indicates:

So you can see the LOWTOUT is not synchronized.   My recommendation when configuring the peripherals is to print out the register bit mapping and highlight the registers that require synchronization. 

To further help with understanding synchronization, consider the following code:

SERCOM0->I2CM.CTRLA.reg =  SERCOM_I2CM_CTRLA_MODE_I2C_MASTER;

The above line does not require synchronization as only the SWRST, ENABLE, and CMD on CTRLA requires synchronization .

Synchronization before write or after write? I generally synchronize after a write to be safe. For example some registers can change before ENABLE bit is set in peripherals. Hence it is not clear what happens if you set the ENABLE bit and the try to change another register before the ENABLE is synchronized, hence I feel it is better to sync after write. 

How to Synchronize 

So in a lot of example code and libraries you will see synchronization done like:

while(SERCOM0->I2CM.STATUS.bit.SYNCBUSY)  {}; 

I personally do not recommend this as that it can end up stalling the processor.  Specifically I have ran into cases where the clocks for peripherals were turned off before sleeping the processor, and then forgotten to turn a peripheral clock on after sleeping.  The result was the processor stalled on the sync bit forever because the peripheral clock was not enabled.  

Of course with a debugger you would think this is easy to find, but it is often very hard to get debugger working again after sleeping.  

Hence I will often put in a timeout system. 

int32_t t0=1000;
while(t0>0 && ptrDevice->ptrSercom->I2CM.STATUS.bit.SYNCBUSY)
{ // Waiting for synchronization t0--;
delay_us(100);
}

Of course the timeout must be longer than the sync time (for the RTC with a slow clock the sync time can be large).  Also how you handle the time out on sync is dependent on your error handling design.  I will do a blog about this shortly. 

Note that most peripheral driver code does not time out on synchronization, for example I have not seen any of the Arduino libraries which have time outs on synchronization.  So be careful what libraries you use as that you might get stuck in the synchronization loop waiting on a watchdog. 

In conclusion Atmel's datasheets are not the clearest on the synchronization, I know I was personally confused for years. So hopefully this article helps clear things up. 

As far as Atmel's datasheets, I keep thinking that maybe we should crowd source rewriting the datasheets and fixing the bugs and errors.