2013-07-08 05:05 AM
When trying to run the LSE oscillator (at 32.768kHz), I stumbled upon the following problem:
PWR->CR |= PWR_CR_DBP; // disable backup-domain lock
RCC->BDCR = RCC_BDCR_LSEON; // enable 32.768kHz oscillator did not result in the LSEON bit being set, unless single-stepped in debugger. Turns out, there must be some delay between the two writes in order the second is accomplished. The reason is, that while the PWR register is at the APB1 bus (and on this 'F4xx design its clock is set to system clock divided by 4), RCC is directly on AHB1. Thus, the write to PWR->CR, after being buffered, has to pass the AHB/APB synchronizer, but meantime the processor may continue by writing into RCC->BDCR, but that gets ignored as the lock has not been removed, yet. A bullet-proof solution might perhaps be similar to:PWR->CR |= PWR_CR_DBP;
while ((RCC->BDCR AND RCC_BDCR_LSERDY) == 0) { // wait until LSE starts up RCC->BDCR = RCC_BDCR_LSEON; // enable 32.768kHz oscillator } (plus optional timeout for case of hardware LSE fault). Browsing through forum I saw several messages reporting a similar problem; however, it's hard to tell what was the root problem in individual cases as they all differ in details (and of course many of the vital information might have remained untold), and in several cases where a solution was found I suspect the ''solution'' just coincidentally masked the root cause. JW #good-catch #lse #stm32-hazard2013-07-08 09:15 AM
It certainly looks to be one of the pipeline/write-buffer hazards as you race to set bits on disparate speed buses, and how quickly the enable propagates from the slower peripheral.
Probably masked for most by the library code return overhead, rather than the inline. Similar issue occur with the interrupt clearing, vs NVIC tail-chain re-entry.2014-05-26 11:00 AM
Got bitten by the same thing second time... oh how dumb I am.
This time it was BACKUP-SRAM writes carefully guarded by PWR_CR.DBP setting on and off... It was quite challenging to find: backup SRAMS were rare, and it worked intermittently due to the processor being delayed/stalled quite a lot by all the interrupts/DMA... plus of course it works flawlessly when single-stepped :( Another issue with BACKUP SRAM came up today too: DMA reads fail if using DMA1 - it took me some time to realize that DMA1's memory port is NOT connected to the whole selection of slaves in the busmatrix... so now I have two branches for that carefully crafted piece of software, DMA for SRAM1/2 and non-DMA for BACKUP SRAM... JW