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

Basic support of clock control in sysctl #10

Merged
merged 1 commit into from
Feb 16, 2021

Conversation

longfangsong
Copy link
Contributor

In the official sdk, sysctl controls different frequencies like pll, aclk(cpu), apb, etc.
This pr tries to add some basic support of setting frequency for pll0 and aclk.

The functions are barely working, but I'm not very sure of the API design.

Self {
cpu: Hertz(403_000_000),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think after k210 startup, the output frequency of pll0 is 780MHz, and for aclk(cpu) it is 390MHz, so the origin data here might be wrong.
However, for UARTHS, both 403_000_000 and 390_000_000 works well here.

Comment on lines +31 to +33
/// The reason why we don't port the complex config algorithm from the
/// official C language SDK is that doing floating number arithmetics
/// efficiently in no_std rust now is currently not very convenient
Copy link
Contributor Author

@longfangsong longfangsong Feb 2, 2021

Choose a reason for hiding this comment

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

Main obstacle I faced with is none of the methods on f64 in std is available in no_std, see this issue. What we need to port the algorithm from C SDK is floor, ceil, round and abs.
Some alternatives I have considered:

  • Use some software floating point library to provide it. This adds a dependency and might not very efficient.
  • Use functions in core::intrinsics, this force the user to use nightly rust.
  • Wrap some asm code directly. Which might be complex and definitly unsafe.

Moreover, that algorithm is too hard to understand.

@longfangsong
Copy link
Contributor Author

longfangsong commented Feb 2, 2021

An example to show how these code working, can run as an example in k210-example:

#![no_std]
#![no_main]

use core::sync::atomic::{compiler_fence, Ordering};
use k210_hal::clock::Clocks;
use k210_hal::pac::{sysctl, SYSCTL};
use k210_hal::{fpioa, pac, prelude::*, stdout::Stdout};
use panic_halt as _;

#[riscv_rt::entry]
fn main() -> ! {
    let p = pac::Peripherals::take().unwrap();

    let mut sysctl = p.SYSCTL.constrain();
    let pll0_freq = sysctl.pll0.set_frequency(400.mhz()); // the result frequency should be 396.5mhz
    let cpu_freq = sysctl.aclk.set_frequency(100.mhz()); // the result frequency should be 99.125mhz

    let fpioa = p.FPIOA.split(&mut sysctl.apb0);
    let gpio = p.GPIO.split(&mut sysctl.apb0);
    let gpiohs = p.GPIOHS.split();

    let clocks = sysctl.clocks();

    // prepare pins
    let _uarths_tx = fpioa.io5.into_function(fpioa::UARTHS_TX);
    fpioa.io16.into_function(fpioa::GPIOHS0);
    let boot_button = gpiohs.gpiohs0.into_pull_up_input();

    // Configure UART
    let serial = p.UARTHS.configure(115_200.bps(), &clocks);
    let (mut tx, _) = serial.split();

    // todo: new stdout design (simple Write impl?)
    let mut stdout = Stdout(&mut tx);

    loop {
        writeln!(stdout, "pll0: {}", pll0_freq.0);
        writeln!(stdout, "aclk: {}", cpu_freq.0);
        writeln!(stdout, "apb0: {}", sysctl.apb0.get_frequency().0);
        writeln!(stdout, "============");
        // sleep 5 seconds
        let start = riscv::register::mcycle::read();
        while riscv::register::mcycle::read() - start < (cpu_freq.0 * 5) as usize {
            compiler_fence(Ordering::SeqCst);
        }
    }
}

@longfangsong longfangsong marked this pull request as ready for review February 13, 2021 08:42
@longfangsong longfangsong changed the title [WIP] Basic support of clock control in sysctl Basic support of clock control in sysctl Feb 13, 2021
@luojia65
Copy link
Collaborator

Thanks! :)

@luojia65 luojia65 merged commit 98fb515 into riscv-rust:master Feb 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants