ch57x_hal_raynhardt/
lib.rs1#![no_std]
2#![recursion_limit = "1024"]
3use core::ptr;
4
5pub use ch57x_pac as pac;
6use qingke::riscv;
7
8pub use self::peripheral::{Peripheral, PeripheralRef};
9pub use self::peripherals::Peripherals;
10
11pub mod adc;
12pub mod dma;
13pub mod gpio;
14#[cfg(feature = "ble")]
17pub mod ble;
18pub mod delay;
19pub mod rtc;
20pub mod signature;
21pub mod spi;
22pub mod sysctl;
23#[cfg(not(feature = "embassy"))]
24pub mod systick;
25pub mod timer;
26pub mod uart;
27
28pub mod interrupt;
29pub mod isp;
30pub mod peripherals;
33
34mod peripheral;
35pub mod prelude;
36
37#[cfg(feature = "embassy")]
38pub mod embassy;
39
40pub type BitsPerSecond = fugit::HertzU32;
42
43pub trait U32Ext {
45 fn bps(self) -> BitsPerSecond;
47}
48
49impl U32Ext for u32 {
50 fn bps(self) -> BitsPerSecond {
51 BitsPerSecond::from_raw(self)
52 }
53}
54
55static mut IRQ_STA: usize = 0;
56
57pub fn with_safe_access<F, R>(f: F) -> R
58where
59 F: FnOnce() -> R,
60{
61 use qingke::register::gintenr;
62
63 const REG_SAFE_ACCESS_SIG: *mut u8 = 0x40001040 as *mut u8;
64 const SAFE_ACCESS_SIG1: u8 = 0x57;
65 const SAFE_ACCESS_SIG2: u8 = 0xA8;
66
67 unsafe {
68 if gintenr::read() & 0x08 != 0 {
69 IRQ_STA = gintenr::read();
70 gintenr::write(IRQ_STA & (!0x08));
71 }
72 riscv::asm::nop();
73 riscv::asm::nop();
74
75 ptr::write_volatile(REG_SAFE_ACCESS_SIG, SAFE_ACCESS_SIG1);
76 ptr::write_volatile(REG_SAFE_ACCESS_SIG, SAFE_ACCESS_SIG2);
77
78 riscv::asm::nop();
79 riscv::asm::nop();
80 }
81 let ret = f();
82 unsafe {
83 ptr::write_volatile(REG_SAFE_ACCESS_SIG, 0);
84 gintenr::write(gintenr::read() | (IRQ_STA & 0x08));
85 IRQ_STA = 0;
86 riscv::asm::nop();
87 riscv::asm::nop();
88 }
89 ret
90}
91
92pub fn delay_us(t: u16) {
93 let t = t as u32;
94 let mut i = match sysctl::clocks().hclk.to_Hz() {
95 60000000 => t * 15,
96 80000000 => t * 20,
97 48000000 => t * 12,
98 32000000 => t * 8,
99 24000000 => t * 6,
100 16000000 => t * 4,
101 8000000 => t * 2,
102 4000000 => t,
103 2000000 => t / 2,
104 1000000 => t / 4,
105 _ => t << 1, };
107 i = i / 8;
108 unsafe {
109 core::arch::asm!(
110 "1:",
111 "nop",
112 "addi {0}, {0}, -1",
113 "bne {0}, zero, 1b",
114 inout(reg) i => _,
115 options(nomem, nostack),
116 );
117 }
118}
119
120pub fn delay_ms(t: u16) {
121 for _ in 0..t {
122 delay_us(1000);
123 }
124}
125
126#[derive(Debug, Clone, Default)]
127pub struct Config {
128 pub clock: sysctl::Config,
129 pub low_power: bool,
131 pub enable_dcdc: bool,
133}
134
135pub fn init(config: Config) -> Peripherals {
136 let sys = unsafe { &*pac::Sys::PTR };
137 if config.enable_dcdc {
138 with_safe_access(|| {
139 sys.r8_aux_power_adj().modify(|_, w| unsafe { w.rb_ulpldo_adj().bits(1) });
140 sys.r16_power_plan().modify(|_, w| w.rb_pwr_dcdc_pre().set_bit());
141 });
142 delay_us(10);
143 with_safe_access(|| {
144 sys.r16_power_plan().modify(|_, w| w.rb_pwr_dcdc_en().set_bit());
145 });
146 } else {
147 with_safe_access(|| {
148 sys.r8_aux_power_adj().modify(|_, w| unsafe { w.rb_ulpldo_adj().bits(0) });
149 sys.r16_power_plan()
150 .modify(|_, w| w.rb_pwr_dcdc_pre().clear_bit().rb_pwr_dcdc_en().clear_bit());
151 });
152 }
153
154 config.clock.freeze();
155
156 if config.low_power {
157 unsafe {
158 let rb = &*pac::Sys::PTR;
159 rb.r32_pa_pd_drv().write(|w| w.bits(0));
161 rb.r32_pa_pu().write(|w| w.bits(0xffff));
162 rb.r32_pa_dir().write(|w| w.bits(0));
163 rb.r32_pb_pd_drv().write(|w| w.bits(0));
165 rb.r32_pb_pu().write(|w| w.bits(0xffff));
166 rb.r32_pb_dir().write(|w| w.bits(0));
167 }
168 }
169
170 Peripherals::take()
171}
172
173pub unsafe fn reset() -> ! {
175 const KEY3: u16 = 0xBEEF;
176 let pfic = unsafe { &*pac::Pfic::PTR };
177 pfic.r32_pfic_cfgr().write(|w| unsafe { w.keycode().bits(KEY3).sysreset().set_bit() });
178 loop {}
179}
180
181pub unsafe fn soft_reset() -> ! {
183 isp::flash_rom_reset();
184
185 let rb = unsafe { &*pac::Sys::PTR };
186 with_safe_access(|| {
187 rb.r8_rst_wdog_ctrl().modify(|_, w| w.rb_software_reset().set_bit());
188 });
189 loop {}
190}
191
192pub static mut SERIAL: Option<uart::UartTx<peripherals::Uart1>> = None;
193
194#[macro_export]
195macro_rules! println {
196 ($($arg:tt)*) => {
197 unsafe {
198 use core::fmt::Write;
199 use core::writeln;
200
201 if let Some(uart) = $crate::SERIAL.as_mut() {
202 writeln!(uart, $($arg)*).unwrap();
203 }
204 }
205 }
206}
207
208pub unsafe fn set_default_serial(serial: uart::UartTx<'static, peripherals::Uart1>) {
209 SERIAL.replace(serial);
210}
211
212pub fn stack_free() -> usize {
213 extern "C" {
214 static mut _ebss: u32;
215 static mut _stack_top: u32;
216 }
217 unsafe { &mut _stack_top as *mut u32 as usize - &mut _ebss as *mut u32 as usize }
218}