From: Tilman Sauerbeck Date: Mon, 17 Jun 2019 05:34:52 +0000 (+0200) Subject: common: Add the clock module. X-Git-Url: http://git.code-monkey.de/?p=gps-watch.git;a=commitdiff_plain;h=4ce1b228434e7b4dfa78f71070e1d063365828eb common: Add the clock module. So far this module only knows how to bring the system to PEE mode. --- diff --git a/SConscript.libcommon b/SConscript.libcommon index 42c0762..69f317c 100644 --- a/SConscript.libcommon +++ b/SConscript.libcommon @@ -5,6 +5,7 @@ source_files_rs = [ 'src/common/lib.rs', # Must be listed first (see below). 'src/common/register.rs', 'src/common/nvic.rs', + 'src/common/clock.rs', ] source_files_c = [ diff --git a/src/common/clock.rs b/src/common/clock.rs new file mode 100644 index 0000000..c1bbb10 --- /dev/null +++ b/src/common/clock.rs @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2019 Tilman Sauerbeck (tilman at code-monkey de) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +use register; + +type Reg8 = register::Register; +type Reg32 = register::Register; + +const SIM_BASE: u32 = 0x40047000; + +const SIM_CLKDIV1: u32 = SIM_BASE + 0x1044; + +const SIM_CLKDIV1_OUTDIV4_SHIFT: u32 = 16; +const SIM_CLKDIV1_OUTDIV1_SHIFT: u32 = 28; + +const MCG_BASE: u32 = 0x40064000; + +const MCG_C1: u32 = MCG_BASE + 0; +const MCG_C2: u32 = MCG_BASE + 1; +const MCG_C4: u32 = MCG_BASE + 3; +const MCG_C5: u32 = MCG_BASE + 4; +const MCG_C6: u32 = MCG_BASE + 5; +const MCG_S : u32 = MCG_BASE + 6; + +const MCG_C1_FRDIV_SHIFT: u32 = 3; +const MCG_C1_CLKS_SHIFT: u32 = 6; + +const MCG_C2_IRCS: u8 = 1 << 0; +const MCG_C2_EREFS0: u8 = 1 << 2; +const MCG_C2_RANGE0_SHIFT: u32 = 4; + +const MCG_C4_DMX32: u8 = 1 << 7; +const MCG_C4_DRST_DRS_MASK: u8 = 3 << 5; + +const MCG_C5_PLLSTEN0: u8 = 1 << 5; +const MCG_C5_PRDIV0_SHIFT: u32 = 0; + +const MCG_C6_VDIV0_SHIFT: u32 = 0; +const MCG_C6_CME0: u8 = 1 << 5; +const MCG_C6_PLLS: u8 = 1 << 6; + +const MCG_S_CLKST_SHIFT: u32 = 2; +const MCG_S_CLKST_MASK: u8 = 3 << MCG_S_CLKST_SHIFT; +const MCG_S_IREFST: u8 = 1 << 4; +const MCG_S_LOCK0: u8 = 1 << 6; + +fn configure_clkdiv() { + let mut clkdiv1 = Reg32::new(SIM_CLKDIV1); + + clkdiv1.write(1 << SIM_CLKDIV1_OUTDIV4_SHIFT); + clkdiv1.modify(|v| v | (1 << SIM_CLKDIV1_OUTDIV1_SHIFT)); +} + +fn switch_to_fbe() { + let mut c2 = Reg8::new(MCG_C2); + c2.write((2 << MCG_C2_RANGE0_SHIFT) | MCG_C2_EREFS0 | MCG_C2_IRCS); + + let mut c1 = Reg8::new(MCG_C1); + c1.write((2 << MCG_C1_CLKS_SHIFT) | (3 << MCG_C1_FRDIV_SHIFT)); + + let mut c4 = Reg8::new(MCG_C4); + c4.modify(|v| v & !MCG_C4_DMX32 & !MCG_C4_DRST_DRS_MASK); + + let mut c5 = Reg8::new(MCG_C5); + c5.write(MCG_C5_PLLSTEN0 | (11 << MCG_C5_PRDIV0_SHIFT)); + + let mut c6 = Reg8::new(MCG_C6); + c6.write(24 << MCG_C6_VDIV0_SHIFT); + + let s = Reg8::new(MCG_S); + + while (s.read() & MCG_S_IREFST) != 0 { + } + + while (s.read() & MCG_S_CLKST_MASK) != (2 << MCG_S_CLKST_SHIFT) { + } +} + +fn switch_to_pbe() { + let mut c1 = Reg8::new(MCG_C1); + c1.write((2 << MCG_C1_CLKS_SHIFT) | (3 << MCG_C1_FRDIV_SHIFT)); + + let mut c2 = Reg8::new(MCG_C2); + c2.write((2 << MCG_C2_RANGE0_SHIFT) | MCG_C2_EREFS0 | MCG_C2_IRCS); + + let mut c5 = Reg8::new(MCG_C5); + c5.write(MCG_C5_PLLSTEN0 | (11 << MCG_C5_PRDIV0_SHIFT)); + + let mut c6 = Reg8::new(MCG_C6); + c6.write(MCG_C6_PLLS | 24 << MCG_C6_VDIV0_SHIFT); + + let s = Reg8::new(MCG_S); + + while (s.read() & MCG_S_CLKST_MASK) != (2 << MCG_S_CLKST_SHIFT) { + } + + while (s.read() & MCG_S_LOCK0) == 0 { + } +} + +fn switch_to_pee() { + let mut c1 = Reg8::new(MCG_C1); + c1.write(3 << MCG_C1_FRDIV_SHIFT); + + let mut c2 = Reg8::new(MCG_C2); + c2.write((2 << MCG_C2_RANGE0_SHIFT) | MCG_C2_EREFS0 | MCG_C2_IRCS); + + let mut c5 = Reg8::new(MCG_C5); + c5.write(MCG_C5_PLLSTEN0 | (11 << MCG_C5_PRDIV0_SHIFT)); + + let mut c6 = Reg8::new(MCG_C6); + c6.write(MCG_C6_PLLS | 24 << MCG_C6_VDIV0_SHIFT); + + let s = Reg8::new(MCG_S); + + while (s.read() & MCG_S_CLKST_MASK) != (3 << MCG_S_CLKST_SHIFT) { + } + + c6.modify(|v| v | MCG_C6_CME0); +} + +pub unsafe fn configure() { + configure_clkdiv(); + + switch_to_fbe(); + switch_to_pbe(); + switch_to_pee(); +} diff --git a/src/common/lib.rs b/src/common/lib.rs index 0fa0f6b..ac388b4 100644 --- a/src/common/lib.rs +++ b/src/common/lib.rs @@ -28,6 +28,7 @@ pub mod register; pub mod nvic; +pub mod clock; #[lang="eh_personality"] extern fn eh_personality() {