Understanding the PRCI clock path

There have been numerous difficulties understanding strange behaviors when setting various configurations of the PRCI clock path of the FE310 SoC. These difficulties arise from two errors in the circuit diagram shown in Figure 2 of Section 6 of version 1p4 of the Manual.

  1. pllbypass mux ‘0’ input connects to output of pllrefsel mux, not the HFX clock source
  2. pllsel mux ‘1’ input connects to output of pllbypass mux, not the PLL output

The diagram as shown in the Manual is below:

The correct diagram is shown below:

One of the clues, explaining (1), is a paragraph of Section 6.5:

The other clue is the fact that, when PLL is turned off (by pllbypass=1), the pllsel is able to control whether hfclk is driven only by HFR or by the selection of pllrefsel.

A few general rules that I discovered, that result in reliable and smooth operation:

  • Change pllrefsel only when pllbypass=1 (PLL off) to prevent PLL unlock and possible latch-up
  • Set pllbypass=0 (PLL on) only when HFR is enabled and pllsel=0, to allow PLL settle and give time to acquire lock condition
  • Change pllrefsel only when HFR is enabled and pllsel=0, to prevent possible latch-up

Some of the earlier discussions related to this topic are
FE310-G002 v1p0 manual errata (@pete_buechler @JimWilson),
Is it possible to brick the HiFive board? (@dvc @mwachs5
Unable to read PRCI registers (@c0ntrarian @pds),
Clock generation and configuration (@stef), and
Dtmcontrol_scan stuck in infinite loop (@tim @pds).

Is it possible to brick the HiFive board? No. However, it is not always easy to completely and successfully reset it. As Tim explains in post above, the core is healthy and undamaged yet the Debug Module is simply stuck in an “always busy” condition, thus OpenOCD loops for a very long time and then gives up.

A typical case of unresponsiveness happens when a bad or buggy program is loaded into Flash (rom), rather than ram. It is very easy to get into seemingly “bricked” states when programming various configurations of the clock flow. Thus, when developing clock routines and algorithms, it is strongly recommended to do so re-targeting code to run only from RAM, where reset will always clear contents of RAM and give successful reset state.

Upon reset, code execution starts immediately. The required task is to completely reset the entire device and start into a halt’ed state. From then, you can erase the first few of the Flash’s blocks and everything is back to normal again.

Typical unresponsive connection from OpenOCD might look like this:

A successful connection looks something like this:

The erasing is done with a few simple steps of OpenOCD tcl commands:

echo [flash protect 0 0 2 off]
echo [flash erase_sector 0 0 2]
echo [flash protect 0 0 2 on]

The reset path of HiFive and LoFive boards involve the AON and PMU blocks and are shown below. The minor difference between boards at the JTAG reset input is not of much concern here:

The time constant of R32 & C22 (or, R4 & C17 on the LoFive board) is very, very long. To make matters worse, the negative-going pulse of AON_PMU_OUT_0 upon reset is only about 400mS. During that short time, the voltage level at the enable input EN of the core vdd_1V8 regulator only makes it down to about 1.2 v. This is not low enough to turn off the voltage regulator and completely reset the CPU.

This is shown in the scope trace below:

When confronted with an apparently “bricked” board, the solution is simple: momentarily bridge C22 (or, C17 on the LoFive board) with a tweezer or long-nose pliers. Then perform the JTAG connection as usual. One more press of the “Reset” button S2 (or, SW1 on the LoFive board) might be needed to fully recover and connect the target into a halt’ed state.