Skip to content
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

cpu/sam0: provide interface to query GCLK frequency #12969

Merged
merged 6 commits into from
Feb 5, 2020

Conversation

benpicco
Copy link
Contributor

Contribution description

The sam0 family offers multiple GCLKs that can be sourced from different timers.
However, all peripherals were effectively always clocked by the hard-coded CLOCK_CORECLOCK.

This causes several issues:

  • on high CPU frequencies (> 51 MHz) the available I2C divider is too small to produce the required I2C baud rate
  • on low CPU frequencies the available frequency is too low to produce high UART baudrates.

This introduces a sam0_gclk_freq() function to query the frequency of the individual GCLKs, so other GCLKs than 0 can be used for peripherals.

This would also allow to change the CPU frequency at run-time without affecting peripherals, unless they use GCLKs sourced from GCLK0.

The first commit in this series also changes the .gclk_src config struct from a bit mask to the GCLK ID.
While not strictly necessary, it cleans up the board configurations and removes the need to differentiate between samd2x and later MCUs.

Testing procedure

In only tested the changes on samr21-xpro and same54-xpro

On same54-xpro you will find that i2c_scan (and I2C in general) now works (USEMODULE += i2c_scan), before it would get stuck due to a wrong clock frequency.

Issues/PRs references

fixes #12037

@benpicco benpicco added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Area: cpu Area: CPU/MCU ports labels Dec 16, 2019
@benpicco benpicco added the State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet label Dec 17, 2019
@benpicco benpicco added State: waiting for other PR State: The PR requires another PR to be merged first State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet and removed State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet State: waiting for other PR State: The PR requires another PR to be merged first labels Dec 20, 2019
@keestux
Copy link
Contributor

keestux commented Jan 16, 2020

Let me mention it once more. There are now a lot of places where the code has 0, 1, 5, etc, but these numbers mean nothing unless you know the (undocumented) values. For example, 0 is for the core clock, 1 is a 1MHz clock, etc.

In the mean time a define was added in periph_cpu.h, namely SAM0_GCLK_32KHZ. Why don't we extend this section and have defines for the other GCLKs? We can add (a brief) description what the GCLK is (frequency, power down mode, etc). Maybe just as a start. And if you're adventurous you could change all these

    .gclk_src       = 0,
...
    .gclk_src       = 1,

into

    .gclk_src       = SAM0_GCLK_MAIN,
...
    .gclk_src       = SAM0_GCLK_1MHZ,

@fjmolinas fjmolinas added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Jan 17, 2020
@benpicco
Copy link
Contributor Author

Alright, that makes sense!
I'll do a separate commit.

@benpicco benpicco removed the State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet label Jan 22, 2020
@benpicco benpicco force-pushed the sam0-gclk branch 2 times, most recently from 89fcbb8 to e48dde5 Compare January 24, 2020 09:07
@dylad
Copy link
Member

dylad commented Jan 31, 2020

I ran dist/tools/compile_and_test_for_board/compile_and_test_for_board.py for SAML10, SAML11, SAML21 and SAME54, so far so good.
If @keestux 's comments were addressed and if SAMD21 is also happy, we should be good to go.

Copy link
Member

@dylad dylad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two small changes.
@keestux @aabadie could you check if samd21 is still happy with this PR please ?
We should be good to go.

@keestux
Copy link
Contributor

keestux commented Feb 4, 2020

It looks good to me.
ACK

@dylad
Copy link
Member

dylad commented Feb 4, 2020

It looks good to me.
ACK

Nice !

@benpicco Please squash !

To simplify board definitions and for unification between samd2x and
newer models, don't use the GCLK bitmask in board definitions.
Instead use the GCLK index and generate the bitmask when needed.
Instead of hard-coding the peripheral clocks to CLOCK_CORECLOCK
introduce helper functions to return the frequency of the individual
GCLKs and use those for baud-rate calculations.

This requires the GCLK to be part of the peripheral's config struct.
While this is already the case for most peripherals, this also adds
it for those where it wasn't used before.

As it defaults to 0 (CLOCK_CORECLOCK) no change is to be expected.
We can't run I2C off the 120 MHz main clock as the availiable dividers are too small.
Use the 48 MHz GCLK 6 instead which offers an appropriate frequency.

fixes RIOT-OS#12037
Use the same 32 kHz GCLK to feed the PLL and the RTT, etc.
Give the clocks explicit names to better identify their meaning.
@benpicco
Copy link
Contributor Author

benpicco commented Feb 4, 2020

Squashed & rebased to the master.

Copy link
Member

@dylad dylad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK.
Thanks for this PR @benpicco !

@dylad
Copy link
Member

dylad commented Feb 5, 2020

Here we go.

@dylad dylad merged commit 83604db into RIOT-OS:master Feb 5, 2020
@benpicco benpicco deleted the sam0-gclk branch February 5, 2020 09:12
@benpicco
Copy link
Contributor Author

benpicco commented Feb 5, 2020

Thank you all for reviewing & testing this!

@@ -72,19 +94,35 @@ static void clk_init(void)
while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC8MRDY)) {}
#endif

/* Setup GCLK2 with divider 1 (32.768kHz) */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benpicco why did you move this up? GCLK->CTRL.reg = GCLK_CTRL_SWRSTresets what is done here, can I move it back down in #13306? Iget the same drift as before otherwise.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you use it for the dfll, I'll move GCLK->CTRL.reg = GCLK_CTRL_SWRS up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm previously this was in the #if CLOCK_USE_PLL block, but a 32kHz clock is always needed so I moved it here.
I must have missed the GCLK_CTRL_SWRS bit.

@leandrolanzieri leandrolanzieri added this to the Release 2020.04 milestone Feb 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

cpu/sam0_common: i2c baudrate calculation fails if CLOCK_CORECLOCK > 51 MHz
6 participants