1#![no_std]
2#![recursion_limit = "1024"]
3use core::ptr;
4
5pub use ch58x::ch58x 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;
14pub mod i2c;
15#[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.aux_power_adj().modify(|_, w| w.dcdc_charge().set_bit());
140 sys.power_plan().modify(|_, w| w.pwr_dcdc_pre().set_bit());
141 });
142 delay_us(10);
143 with_safe_access(|| {
144 sys.power_plan().modify(|_, w| w.pwr_dcdc_en().set_bit());
145 });
146 } else {
147 with_safe_access(|| {
148 sys.aux_power_adj().modify(|_, w| w.dcdc_charge().clear_bit());
149 sys.power_plan()
150 .modify(|_, w| w.pwr_dcdc_pre().clear_bit().pwr_dcdc_pre().clear_bit());
151 });
152 }
153
154 config.clock.freeze();
155
156 if config.low_power {
157 unsafe {
158 for rb in [&*pac::GPIOA::PTR, &*pac::GPIOB::PTR] {
159 rb.pd_drv().write(|w| w.bits(0));
161 rb.pu().write(|w| w.bits(0xffff));
162 rb.dir().write(|w| w.bits(0));
163 }
164 }
165 }
166
167 Peripherals::take()
168}
169
170pub unsafe fn reset() -> ! {
172 const KEY3: u16 = 0xBEEF;
173 let pfic = unsafe { &*pac::PFIC::PTR };
174 pfic.cfgr().write(|w| w.keycode().variant(KEY3).resetsys().set_bit());
175 loop {}
176}
177
178pub unsafe fn soft_reset() -> ! {
180 isp::flash_rom_reset();
181
182 let rb = unsafe { &*pac::SYS::PTR };
183 with_safe_access(|| {
184 rb.rst_wdog_ctrl().modify(|_, w| w.software_reset().set_bit());
185 });
186 loop {}
187}
188
189pub static mut SERIAL: Option<uart::UartTx<peripherals::UART1>> = None;
190
191#[macro_export]
192macro_rules! println {
193 ($($arg:tt)*) => {
194 unsafe {
195 use core::fmt::Write;
196 use core::writeln;
197
198 if let Some(uart) = $crate::SERIAL.as_mut() {
199 writeln!(uart, $($arg)*).unwrap();
200 }
201 }
202 }
203}
204
205pub unsafe fn set_default_serial(serial: uart::UartTx<'static, peripherals::UART1>) {
206 SERIAL.replace(serial);
207}
208
209pub fn stack_free() -> usize {
210 extern "C" {
211 static mut _ebss: u32;
212 static mut _stack_top: u32;
213 }
214 unsafe { &mut _stack_top as *mut u32 as usize - &mut _ebss as *mut u32 as usize }
215}