-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework PLL calculation and utilize oscillator clock divison #67
Conversation
Reminder: Compare with |
bc0e0a9
to
c2a73e7
Compare
Going through these quite complicated clock trees: Another reminder. stm32f303d/e does have an extra PREDIV block, while stm32f302d/e does not. stm32f303d/e: stm32f302d/e: |
93c9d48
to
7ad0346
Compare
6afee57
to
6b2446f
Compare
So I tested it on different clock configuration on hardware, seeing if the clock configuration is correctly initialized and most things worked as expected. Now it is possible to choose clocks like 14 MHz on an 8 MHz based Oscillator clocks. However, with 9 MHz I had a strange problem I used itm (
But on 9 MHz |
I feel like this is ready to be review again. I don't like the way that the rcc module contains so many asserts, which keeping coming up, when using a wrong configuration. A better documentation for valid clock settings or a way to propagate the error to the user is needed. But this is not scope of this PR. @russellmcc maybe you'd like to take another look. If not I'll ask somebody else. I'm comfortable merging this code as is but would like to have it reviewed, as this is code everybody depends upon, when using this hal. |
Initially this should fix the case, that the system clock calculation assumed that HSI was always devided by 2 for any device. As the initial state hat some problems this ended up being a rework of the PLL calculation to resemble the clock tree setup of stm32f3xx mitrockrollers more closely. The difference between different devices can be divided into two categories: 1. Devices which have the possibility to configure HSI dividend The clock tree of the stm32f303xd as an example: https://www.st.com/content/ccc/resource/technical/document/reference_manual/4a/19/6e/18/9d/92/43/32/DM00043574.pdf/files/DM00043574.pdf/jcr:content/translations/en.DM00043574.pdf#page=127 2. Devices which always divide HSI by 2 The clock tree of the stm32f303x6 as an example: https://www.st.com/content/ccc/resource/technical/document/reference_manual/4a/19/6e/18/9d/92/43/32/DM00043574.pdf/files/DM00043574.pdf/jcr:content/translations/en.DM00043574.pdf#page=128 For [1] the HSI is not initially divided by 2 and both HSE and HSI can be changed via divisor block (PRE_DVI) and multiplier block (PLL_MUL). For [2] the HSI is **always** divided by by 2 and the divisor can only be used for the HSE. These differences also apply to the stm32f302x{b,c,d,e}, so these targets get added as a feature. With this rewrite it is now possible to get more fine grained control over the system clock we can choose. To find out the optimal values for both the multiplier and the divisor, a greatest common divisor calculation is used. Some examples: - If you want 72 Mhz system clock out of 32 Mhz oscillator clock the common divisor would be 8. Represented in a fraction this would look like this: 72 / 32 = (72 / 8) / (32 / 8) = 9 / 4 These values can be represented in the divisor and multiplier block, as these can take values up to 16. - If you want 26 Mhz system clock out of 8 Mhz oscillator clock the common divisor would be 2. Represented in a fraction this would look like this: 26 / 8 = (26 / 2) / (8 / 2) = 13 / 4
Rework
This PR turned out to be rework of the PLL setup.
Now
get _sysclk
will choose, whether PLL is needed as the source for the system clock.The
usb_valid
check should work just fine, as we need the PLL anyways to get the supported frequencies (48 MHz and 72 MHz). Both can not be directly generated from the external oscillator as theHSE OSC
does only allow up to 32 MHz.calc_pll
does now calculate the optimal divisor and multiplier values to generate the system clock, which the user provides. For that the greatest common divisor calculation is used, because the range of the possible values, which the PRE_DIV and PLL_MUL can take is 16 in both cases.calc_pll
is split into 2 implementations, one for devices which only can adjust the division of the clock of the external oscillator.The other one, where both HSI and HSE division can be adjusted.
Now that the divisor (PRE_DIV) is utilized, 48 MHz and 72 MHz can be generated out of a 32 MHz
48 MHz / 32 MHz
can be simplified to3 / 2
as the greatest common divisor is16
.PLL_MUL
is now set to3
and PRE_DIV is set to2
.Similarly,
72 MHz / 32 MHz
can be simplified to9 / 4
as the greatest common divisor is8
.Fix
Initially a fix, which removes HSI division for devices, which do not divide HSI.
Fix #57
Ref #57 (comment)
Relevant parts in the reference manual:
with
/2
divisor after HSIwithout
/2
divisor after HSI