summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/boards/pllvalues.py
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/boards/pllvalues.py')
-rw-r--r--stmhal/boards/pllvalues.py115
1 files changed, 115 insertions, 0 deletions
diff --git a/stmhal/boards/pllvalues.py b/stmhal/boards/pllvalues.py
new file mode 100644
index 0000000000..183313f304
--- /dev/null
+++ b/stmhal/boards/pllvalues.py
@@ -0,0 +1,115 @@
+"""
+This is an auxiliary script that is used to compute valid PLL values to set
+the CPU frequency to a given value. The algorithm here appears as C code
+for the machine.freq() function.
+"""
+
+def close_int(x):
+ return abs(x - round(x)) < 0.01
+
+# original version that requires N/M to be an integer (for simplicity)
+def compute_pll(hse, sys):
+ for P in (2, 4, 6, 8): # allowed values of P
+ Q = sys * P / 48
+ NbyM = sys * P / hse
+ # N/M and Q must be integers
+ if not (close_int(NbyM) and close_int(Q)):
+ continue
+ # VCO_OUT must be between 192MHz and 432MHz
+ if not (192 <= hse * NbyM <= 432):
+ continue
+ # compute M
+ M = int(192 // NbyM)
+ while hse > 2 * M or NbyM * M < 192:
+ M += 1
+ # VCO_IN must be between 1MHz and 2MHz (2MHz recommended)
+ if not (M <= hse):
+ continue
+ # compute N
+ N = NbyM * M
+ # N and Q are restricted
+ if not (192 <= N <= 432 and 2 <= Q <= 15):
+ continue
+ # found valid values
+ assert NbyM == N // M
+ return (M, N, P, Q)
+ # no valid values found
+ return None
+
+# improved version that doesn't require N/M to be an integer
+def compute_pll2(hse, sys):
+ for P in (2, 4, 6, 8): # allowed values of P
+ Q = sys * P / 48
+ # Q must be an integer in a set range
+ if not (close_int(Q) and 2 <= Q <= 15):
+ continue
+ NbyM = sys * P / hse
+ # VCO_OUT must be between 192MHz and 432MHz
+ if not (192 <= hse * NbyM <= 432):
+ continue
+ # compute M
+ M = 192 // NbyM # starting value
+ while hse > 2 * M or NbyM * M < 192 or not close_int(NbyM * M):
+ M += 1
+ # VCO_IN must be between 1MHz and 2MHz (2MHz recommended)
+ if not (M <= hse):
+ continue
+ # compute N
+ N = NbyM * M
+ # N must be an integer
+ if not close_int(N):
+ continue
+ # N is restricted
+ if not (192 <= N <= 432):
+ continue
+ # found valid values
+ return (M, N, P, Q)
+ # no valid values found
+ return None
+
+def verify_and_print_pll(hse, sys, pll):
+ M, N, P, Q = pll
+
+ # compute derived quantities
+ vco_in = hse / M
+ vco_out = hse * N / M
+ pllck = hse / M * N / P
+ pll48ck = hse / M * N / Q
+
+ # verify ints
+ assert close_int(M)
+ assert close_int(N)
+ assert close_int(P)
+ assert close_int(Q)
+
+ # verify range
+ assert 2 <= M <= 63
+ assert 192 <= N <= 432
+ assert P in (2, 4, 6, 8)
+ assert 2 <= Q <= 15
+ assert 1 <= vco_in <= 2
+ assert 192 <= vco_out <= 432
+
+ # print out values
+ print(out_format % (sys, M, N, P, Q, vco_in, vco_out, pllck, pll48ck))
+
+def main():
+ global out_format
+ import sys
+ if len(sys.argv) != 2:
+ print("usage: pllvalues.py <hse in MHz>")
+ sys.exit(1)
+ hse_value = int(sys.argv[1])
+ print("HSE =", hse_value, "MHz")
+ print("sys : M N P Q : VCO_IN VCO_OUT PLLCK PLL48CK")
+ out_format = "%3u : %2u %.1f %.2f %.2f : %5.2f %6.2f %6.2f %6.2f"
+ n_valid = 0
+ for sysclk in range(1, 217):
+ pll = compute_pll2(hse_value, sysclk)
+ if pll is not None:
+ n_valid += 1
+ verify_and_print_pll(hse_value, sysclk, pll)
+ print("found %u valid configurations" % n_valid)
+
+if __name__ == "__main__":
+ main()