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