RIOT-OS / RIOT

RIOT - The friendly OS for IoT
https://riot-os.org
GNU Lesser General Public License v2.1
4.83k stars 1.97k forks source link

samd21: pull all generic clock generators into clock.c #7208

Closed photonthunder closed 4 years ago

photonthunder commented 7 years ago

The samd21 has 9 generic clock generators that can be tied to different clock sources and then tweaked for the users needs. Currently these are setup in clock.c, timer.c, rtt.c, and rtc.c. Wanted to open a discussion about cleaning this up. I recommend we pull all generic clock generator code back into clock.c and setup a specific clock generator for a specific clock. For example:

#if GEN1_1MHZ
    /* configure internal 8MHz oscillator to run without prescaler */
    SYSCTRL->OSC8M.bit.PRESC = 0;
    SYSCTRL->OSC8M.bit.ONDEMAND = 1;
    SYSCTRL->OSC8M.bit.RUNSTDBY = 0;
    SYSCTRL->OSC8M.bit.ENABLE = 1;
    while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC8MRDY)) {}

    /* setup generic clock 1 as 1MHz */
    GCLK->GENDIV.reg =  (GCLK_GENDIV_DIV(8) | GCLK_GENDIV_ID(1));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_SRC_OSC8M |
                         GCLK_GENCTRL_ID(1));
    GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_GEN(1) |
                         GCLK_CLKCTRL_ID(1) |
                         GCLK_CLKCTRL_CLKEN);
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
#endif

#if GEN2_XOSC32
    /* configure 32kHz external oscillator */
    SYSCTRL->XOSC32K.reg = (SYSCTRL_XOSC32K_ONDEMAND |
                            SYSCTRL_XOSC32K_EN32K |
                            SYSCTRL_XOSC32K_XTALEN |
#if XOSC32_RUNSTDBY
                            SYSCTRL_XOSC32K_RUNSTDBY |
#endif
                            SYSCTRL_XOSC32K_STARTUP(6));

    /* Enable with Seperate Call */
    SYSCTRL->XOSC32K.bit.ENABLE = 1;

    /* setup generic clock 2 as 32 kHz */
    GCLK->GENDIV.reg =  (GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(1));
    GCLK->GENCTRL.reg =  (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_ID(2) |
#if XOSC32_RUNSTDBY
                         GCLK_GENCTRL_RUNSTDBY |
#endif
                         GCLK_GENCTRL_SRC_XOSC32K);
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
#endif

#if GEN3_ULP32K
    /* Setup Clock generator 3 with divider 1 (32.768kHz) */
    GCLK->GENDIV.reg  = (GCLK_GENDIV_ID(3)  | GCLK_GENDIV_DIV(0));
    GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN |
                         GCLK_GENCTRL_ID(3) |
                         GCLK_GENCTRL_RUNSTDBY |
                         GCLK_GENCTRL_SRC_OSCULP32K);
    while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
#endif

Then in timer.c/rtt.c/rtc.c and so forth you just check that the clock is on then use it:

#if GEN2_XOSC32 == 0
#error Must turn on GEN2_XOSC32 to use RTT
#endif

    /* RTC uses GEN2_XOSC32 because OSC32K isn't accurate
     * enough (p1075/1138). Also keep running in standby. */
    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN_GCLK2 |
                        GCLK_CLKCTRL_CLKEN |
                        GCLK_CLKCTRL_ID(RTC_GCLK_ID);
    while (GCLK->STATUS.bit.SYNCBUSY) {}

See PR #7130 for motivation for this issue.

Thoughts, input?

jnohlgard commented 7 years ago

Unassigning because I have just about zero experience with the Atmel SAM families.

dylad commented 7 years ago

This discussion can be expanded to SAML21 as its also have 9 generic clock module. Personally, I think moving all those init into clock.c is a good idea. And user should only modify the periph_conf.h file to obtain the desired behaviour regarding clock management without overwrite clock.c

photonthunder commented 7 years ago

Submitted PR #7315 to try and move this forward. Once it is accepted then we can expand it to SAML21.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions.