Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 35 additions & 119 deletions modules/axhal/src/platform/aarch64_phytium_pi/clock.rs
Original file line number Diff line number Diff line change
@@ -1,132 +1,48 @@
use core::ptr::NonNull;
use tock_registers::{
interfaces::{Readable, ReadWriteable},
register_bitfields, register_structs,
registers::{ReadOnly, ReadWrite},
};
use kspin::SpinNoIrq;
use crate::mem::{phys_to_virt, PhysAddr};
use aarch64_cpu::registers::CNTFRQ_EL0;
use aarch64_cpu::registers::Readable;


register_structs! {
pub ClockRegs {
(0x00 => clk_con: ReadWrite<u32, CLK_CON::Register>),
(0x04 => clk_div: ReadWrite<u32, CLK_DIV::Register>),
(0x08 => clk_status: ReadOnly<u32, CLK_STATUS::Register>),
(0x0c => @END),
}
static mut GLOBAL_CLOCK: Option<Clock> = None;
#[derive(Debug, Clone, Copy)]
pub struct Clock {
pub frequency: u32, // 系统时钟频率(Hz)
pub div:u32,
pub sys_frequency:u32,
}

register_bitfields![u32,
CLK_CON [
ENABLE OFFSET(0) NUMBITS(1) [], // 1=使能时钟
SOURCE OFFSET(1) NUMBITS(3) [], // 时钟源选择
],
CLK_DIV [
DIV OFFSET(0) NUMBITS(8) [], // 分频系数
],
CLK_STATUS [
READY OFFSET(0) NUMBITS(1) [], // 1=时钟准备好
],
];

// Clock 控制器结构体
pub struct ClockCtrl {
regs: NonNull<ClockRegs>,
}
impl Clock {
/// 构造函数,自动从CNTFRQ_EL0寄存器读取频率
pub fn new() -> Self {
let freq = CNTFRQ_EL0.get() as u32;
Clock { frequency: freq, div: 1, sys_frequency: freq }
}

unsafe impl Send for ClockCtrl {}
/// 获取系统时钟频率(Hz)
pub fn get_frequency(&self) -> u32 {
self.frequency
}

impl ClockCtrl {
pub const fn new(base: *mut u8) -> Self {
Self {
regs: NonNull::new(base).unwrap().cast(),
}
}
const fn regs(&self) -> &ClockRegs {
unsafe { self.regs.as_ref() }
pub fn set_frequency(&mut self, freq: u32) {
self.frequency = freq;
self.div = freq / self.sys_frequency;
}
const fn regs_mut(&mut self) -> &mut ClockRegs {
unsafe { self.regs.as_mut() }
}
}

// API 实现
#[derive(Debug, Clone, Copy, Default)]
pub struct FClockConfig {
pub instance_id: u32,
pub base_address: usize,
}

#[derive(Clone, Copy)]
pub struct FClockCtrl {
pub config: FClockConfig,
pub is_ready: u32,
}

static CLOCK_CONFIG: [FClockConfig; 1] = [FClockConfig {
instance_id: 0,
base_address: 0x2800_0000usize,
}];

pub static CLOCK: SpinNoIrq<FClockCtrl> = SpinNoIrq::new(FClockCtrl {
config: FClockConfig {
instance_id: 0,
base_address: 0,
},
is_ready: 0,
});

pub fn FClockInit(instance_p: &mut FClockCtrl, config_p: &FClockConfig) -> bool {
assert!(instance_p as *const _ as usize != 0 && config_p as *const _ as usize != 0);
let ret = true;
if instance_p.is_ready == 0x11111111u32 {
info!("Clock already initialized.");
return false;
}
FClockDeInit(instance_p);
instance_p.config = *config_p;
instance_p.is_ready = 0x11111111u32;
ret
}

pub fn FClockDeInit(instance_p: &mut FClockCtrl) -> bool {
if instance_p.is_ready == 0 {
return true;
pub fn get_div(&self) -> u32 {
self.div
}
instance_p.is_ready = 0;
unsafe {
core::ptr::write_bytes(instance_p as *mut FClockCtrl, 0, core::mem::size_of::<FClockCtrl>());
pub fn get_sys_frequency(&self) -> u32 {
self.sys_frequency
}
true
}

pub fn FClockLookupConfig(instance_id: u32) -> Option<FClockConfig> {
if instance_id >= 1 {
return None;
}
Some(CLOCK_CONFIG[instance_id as usize])
}
pub fn init_global() {
// 将基地址转换为NonNull<u8>
let mut clock = Clock::new(); // 初始化时钟
info!("Clock frequency: {} Hz", clock.get_frequency());
clock.set_frequency(200_000_000);
info!("Clock frequency: {} Hz", clock.get_frequency());

pub fn FClockSetFreq(instance_p: &mut FClockCtrl, freq: u32) -> bool {
let base = instance_p.config.base_address;
let clock = ClockCtrl::new(phys_to_virt(PhysAddr::from(base)).as_mut_ptr());
let sys_clk = 50000000; // 50MHz 系统时钟
let div = sys_clk / freq;
clock.regs().clk_div.modify(CLK_DIV::DIV.val(div));
clock.regs().clk_con.modify(CLK_CON::ENABLE::SET);
let mut timeout = 0;
while clock.regs().clk_status.read(CLK_STATUS::READY) != 1 && timeout < 500 {
timeout += 1;
crate::time::busy_wait(core::time::Duration::from_millis(1));
// 存储到全局静态变量
unsafe {
GLOBAL_CLOCK = Some(clock);
}
}
timeout < 500
}

pub fn FClockGetFreq(instance_p: &mut FClockCtrl) -> u32 {
let base = instance_p.config.base_address;
let clock = ClockCtrl::new(phys_to_virt(PhysAddr::from(base)).as_mut_ptr());
let sys_clk = 50000000; // 50MHz 系统时钟
let div = clock.regs().clk_div.read(CLK_DIV::DIV);
sys_clk / div
}
5 changes: 1 addition & 4 deletions modules/axhal/src/platform/aarch64_phytium_pi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,7 @@ pub fn platform_init() {
&mut pinctrl::PAD.lock(),
&pinctrl::FIOPadLookupConfig(0).unwrap(),
);
clock::FClockInit(
&mut clock::CLOCK.lock(),
&clock::FClockLookupConfig(0).unwrap(),
);
clock::Clock::init_global();
pwm::PwmCtrl::init_global();
driver_gpio::init_gpio();
driver_watchdog::init_watchdog();
Expand Down