AnsweredAssumed Answered

Procedure for changing FLASH waitstates

Question asked by waclawek.jan on Mar 25, 2013
While playing with some benchmarking code on STM32F4, I came across an interesting phenomenon: I was changing the FLASH waitstate in the LATENCY field of FLASH_ACR register, and sometimes the subsequent code run at a different speed than I have set.

When trying to put a breakpoint at or after the point where the FLASH_ACR register was set, and reading back its content, it matched the written value and the code run properly as expected. It was even enough to stop and continue at that point to have the code run properly.

When simply reading back the register in runtime and storing it in a variable to be inspected later, the variable sometimes contained a surprising value indeed. For example, when changing FLASH_ACR from 0x105 to 0x106 (both caches off, prefetch on, changing waitstates from 5 to 6), the readout was 0x1, and the subsequently the benchmarking function indeed run in the same time as when I set FLASH_ACR explicitly to 0x1. (This, btw. sounds to me as potential source of serious troubles, as if this would happen at a high enough system frequency, the whole shebang would hiccup on the incorrectly fetched instructions).

Reading back the register and compare to the value written appears to work in 100% of cases, although of course only ST can confirm whether this is a bullet-proof method or not:
      FLASH->ACR = new_ACR_value;
      while (FLASH->ACR != new_ACR_value);

Whether such "glitch" happens or not, appears to depend on whether the code before and after the switch can keep the whole FLASH interface busy. That is probably the reason why breaking in using the debugger "helps" - it stalls the processor and allows the FLASH interface to correctly finish the write into the register. And also the reason why this issue went unnoticed so far - with the caches on, and in a typical code where at higher speeds (when the higher values of latency are used) accesses to peripherals imply several waitstates, it's quite likely that the FLASH interface is idle for quite some period of time.

ST appears to be aware of the problem, and by carefully following *all* hints in the manual it can be avoided. In 3.4.1 of RM0090 v4, the following can be read:
"Check that the new number of wait states is taken into account to access the Flash
memory by reading the FLASH_ACR register"
and
"A change in CPU clock configuration or wait state (WS) configuration may not be effective
straight away.[...] To make sure that the number of WS you have programmed is effective, you can [sic!] read the FLASH_ACR register."

However, the description of FLASH_ACR register does not warn accordingly, and in the "library" I see no hint of reading back the FLASH_ACR register after changing its value.

So, if ST reads this, I'd suggest:
- to reformulate Note on page 63 to *require* to read back FLASH_ACR after writing
- to put a Note to the FLASH_ACR register with outlining a bulletproof method of changing it
- to modify the "library" so that the routines writing to FLASH_ACR implement the bulletproof method; the plain write in the "startup" files could be left alone if ST deems changing from the reset state (all 0) to any other state safe enough; however, this then should be documented properly too.

Jan Waclawek

Outcomes