This topic is very difficult to me and everytime I have many doubts.
I need to avoid bus stall in every situations. This mainly because during bus stall pending interrupt requests are blocked. In order to avoid bus stall, some registers (the registers that are tagged with Read-Synchronized and Write-Sinchronized) must be read and/or written with great care.
I think I understood that the problem is present even if the registers are clocked from the same source as the Main CPU. From datasheet:
This mechanism is implemented in hardware, so the synchronization process takes place even if the peripheral generic clock is running from the same clock source and on the same frequency as the bus interface.
For example, suppose I have this config: XOSC (16MHz crystal) -> Gen0 (without division, Main CPU) -> GCLK TC0 (without prescaler). TC0 and CPU runs at the same frequency.
Now, what happens when I want to read COUNT register from TC0? If I read it without taking into account the synchronization probem, the bus stall happens for a period that is 5×P_GCLK + 2×P_APB < D < 6×P_GCLK + 3×P_APB. P_GCLK and P_APB are the same, so: 7×P_GCLK < D < 9×P_GCLK. In the worst case, I loose 9 clock pulses to read a simple register from a Timer/Counter peripheral. During bus stall interrupts aren't served.
I can improve this prepending the reading of COUNT register with a read request and a sync loop:
TC0->COUNT32.READREQ.bit |= TC_READREQ_RREQ;
counter = TC0->COUNT32.COUNT.reg;
Here I transformed the bus stall period in a delay loop, when the interrupts can be served. However the 9 clock pulses are always there.
Now imagine the following classical situation:
OSC32K (32.768kHz) -> GCLK Gen 1 (32.768kHz) -> DFLL48M (48MHz) -> GCLK Gen 0 (48MHz, Main CPU)
OSC32K (32.768kHz) -> GCLK Gen 2 div 32 (1.024kHz) -> RTC (prescaler 1024, 1Hz)
RTC is configured as a 32-bits counter with a counting frequency of 1Hz. I use it as the date/time for the application (the number of seconds from an epoch).
What happens when the CPU wants to read the current time, so reading RTC->MODE0.COUNT.reg? I need to wait for sync delay that, in the worst case, is 6×P_GCLK + 3×P_APB. P_GCLK=1.024kHz and P_APB=48MHz so sync maximum delay is about 6ms!!!
Of course, with read request and sync loop I could serve interrupts, but I can't block my application for 6ms only to read a simple register!!
I read about continuous synchronization and I tried to implement, without success.
static inline void rtc_init(void)
RTC_MODE0_CTRL_MODE_COUNT32 | // Mode 0 = 32-bits counter
RTC_MODE0_CTRL_PRESCALER_DIV1024; // Divisor = 1024
RTC_READREQ_RCONT; // Enable continuous synch
RTC_MODE0_CTRL_ENABLE; // Enable peripheral
static inline uint32_t rtc_get_clock(void)
uint32_t ret = RTC->MODE0.COUNT.reg;
On the oscilloscope on spare pin, I always see a pulse of about 6ms, even if the RCONT bit is set. An it seems the bust stall happens. Why? I tried with example project from ASF (RTC_QUICK_START_COUNT_POLLED) and it seems the bus stall always happens.
It appears to me that READREQ functionality doesn't work as expected.