diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index b68f9538..49aa6a4d 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -76,7 +76,7 @@ embedded-storage = { version = "0.3" } rand_core = "0.6.4" fixed = "1.23.1" -rp-pac = { version = "4" } +rp-pac = { version = "5" } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index f29c4dfe..b96d5a4a 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -50,16 +50,14 @@ impl<'d> Adc<'d> { _irq: impl Binding, _config: Config, ) -> Self { - unsafe { - let reset = Self::reset(); - crate::reset::reset(reset); - crate::reset::unreset_wait(reset); - let r = Self::regs(); - // Enable ADC - r.cs().write(|w| w.set_en(true)); - // Wait for ADC ready - while !r.cs().read().ready() {} - } + let reset = Self::reset(); + crate::reset::reset(reset); + crate::reset::unreset_wait(reset); + let r = Self::regs(); + // Enable ADC + r.cs().write(|w| w.set_en(true)); + // Wait for ADC ready + while !r.cs().read().ready() {} // Setup IRQ interrupt::ADC_IRQ_FIFO.unpend(); @@ -70,80 +68,70 @@ impl<'d> Adc<'d> { async fn wait_for_ready() { let r = Self::regs(); - unsafe { - r.inte().write(|w| w.set_fifo(true)); - compiler_fence(Ordering::SeqCst); - poll_fn(|cx| { - WAKER.register(cx.waker()); - if r.cs().read().ready() { - return Poll::Ready(()); - } - Poll::Pending - }) - .await; - } + r.inte().write(|w| w.set_fifo(true)); + compiler_fence(Ordering::SeqCst); + poll_fn(|cx| { + WAKER.register(cx.waker()); + if r.cs().read().ready() { + return Poll::Ready(()); + } + Poll::Pending + }) + .await; } pub async fn read, ID = u8> + Pin>(&mut self, pin: &mut PIN) -> u16 { let r = Self::regs(); - unsafe { - // disable pull-down and pull-up resistors - // pull-down resistors are enabled by default - pin.pad_ctrl().modify(|w| { - w.set_ie(true); - let (pu, pd) = (false, false); - w.set_pue(pu); - w.set_pde(pd); - }); - r.cs().modify(|w| { - w.set_ainsel(PIN::channel()); - w.set_start_once(true) - }); - Self::wait_for_ready().await; - r.result().read().result().into() - } + // disable pull-down and pull-up resistors + // pull-down resistors are enabled by default + pin.pad_ctrl().modify(|w| { + w.set_ie(true); + let (pu, pd) = (false, false); + w.set_pue(pu); + w.set_pde(pd); + }); + r.cs().modify(|w| { + w.set_ainsel(PIN::channel()); + w.set_start_once(true) + }); + Self::wait_for_ready().await; + r.result().read().result().into() } pub async fn read_temperature(&mut self) -> u16 { let r = Self::regs(); - unsafe { - r.cs().modify(|w| w.set_ts_en(true)); - if !r.cs().read().ready() { - Self::wait_for_ready().await; - } - r.cs().modify(|w| { - w.set_ainsel(4); - w.set_start_once(true) - }); + r.cs().modify(|w| w.set_ts_en(true)); + if !r.cs().read().ready() { Self::wait_for_ready().await; - r.result().read().result().into() } + r.cs().modify(|w| { + w.set_ainsel(4); + w.set_start_once(true) + }); + Self::wait_for_ready().await; + r.result().read().result().into() } pub fn blocking_read, ID = u8>>(&mut self, _pin: &mut PIN) -> u16 { let r = Self::regs(); - unsafe { - r.cs().modify(|w| { - w.set_ainsel(PIN::channel()); - w.set_start_once(true) - }); - while !r.cs().read().ready() {} - r.result().read().result().into() - } + r.cs().modify(|w| { + w.set_ainsel(PIN::channel()); + w.set_start_once(true) + }); + while !r.cs().read().ready() {} + r.result().read().result().into() } pub fn blocking_read_temperature(&mut self) -> u16 { let r = Self::regs(); - unsafe { - r.cs().modify(|w| w.set_ts_en(true)); - while !r.cs().read().ready() {} - r.cs().modify(|w| { - w.set_ainsel(4); - w.set_start_once(true) - }); - while !r.cs().read().ready() {} - r.result().read().result().into() - } + r.cs().modify(|w| w.set_ts_en(true)); + while !r.cs().read().ready() {} + r.cs().modify(|w| { + w.set_ainsel(4); + w.set_start_once(true) + }); + while !r.cs().read().ready() {} + r.result().read().result().into() } } diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 67439fda..4c622310 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -542,7 +542,7 @@ pub(crate) unsafe fn init(config: ClockConfig) { reset::unreset_wait(peris); } -unsafe fn configure_rosc(config: RoscConfig) -> u32 { +fn configure_rosc(config: RoscConfig) -> u32 { let p = pac::ROSC; p.freqa().write(|w| { @@ -620,7 +620,7 @@ pub fn clk_rtc_freq() -> u16 { CLOCKS.rtc.load(Ordering::Relaxed) } -unsafe fn start_xosc(crystal_hz: u32) { +fn start_xosc(crystal_hz: u32) { pac::XOSC .ctrl() .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); @@ -635,7 +635,7 @@ unsafe fn start_xosc(crystal_hz: u32) { } #[inline(always)] -unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 { +fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 { let ref_freq = input_freq / config.refdiv as u32; assert!(config.fbdiv >= 16 && config.fbdiv <= 320); assert!(config.post_div1 >= 1 && config.post_div1 <= 7); @@ -700,9 +700,7 @@ impl<'d, T: Pin> Gpin<'d, T> { pub fn new(gpin: impl Peripheral

+ 'd) -> Gpin<'d, P> { into_ref!(gpin); - unsafe { - gpin.io().ctrl().write(|w| w.set_funcsel(0x08)); - } + gpin.io().ctrl().write(|w| w.set_funcsel(0x08)); Gpin { gpin: gpin.map_into(), @@ -717,12 +715,10 @@ impl<'d, T: Pin> Gpin<'d, T> { impl<'d, T: Pin> Drop for Gpin<'d, T> { fn drop(&mut self) { - unsafe { - self.gpin - .io() - .ctrl() - .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); - } + self.gpin + .io() + .ctrl() + .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); } } @@ -768,53 +764,43 @@ impl<'d, T: GpoutPin> Gpout<'d, T> { pub fn new(gpout: impl Peripheral

+ 'd) -> Self { into_ref!(gpout); - unsafe { - gpout.io().ctrl().write(|w| w.set_funcsel(0x08)); - } + gpout.io().ctrl().write(|w| w.set_funcsel(0x08)); Self { gpout } } pub fn set_div(&self, int: u32, frac: u8) { - unsafe { - let c = pac::CLOCKS; - c.clk_gpout_div(self.gpout.number()).write(|w| { - w.set_int(int); - w.set_frac(frac); - }); - } + let c = pac::CLOCKS; + c.clk_gpout_div(self.gpout.number()).write(|w| { + w.set_int(int); + w.set_frac(frac); + }); } pub fn set_src(&self, src: GpoutSrc) { - unsafe { - let c = pac::CLOCKS; - c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { - w.set_auxsrc(ClkGpoutCtrlAuxsrc(src as _)); - }); - } + let c = pac::CLOCKS; + c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { + w.set_auxsrc(ClkGpoutCtrlAuxsrc(src as _)); + }); } pub fn enable(&self) { - unsafe { - let c = pac::CLOCKS; - c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { - w.set_enable(true); - }); - } + let c = pac::CLOCKS; + c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { + w.set_enable(true); + }); } pub fn disable(&self) { - unsafe { - let c = pac::CLOCKS; - c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { - w.set_enable(false); - }); - } + let c = pac::CLOCKS; + c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { + w.set_enable(false); + }); } pub fn get_freq(&self) -> u32 { let c = pac::CLOCKS; - let src = unsafe { c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc() }; + let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc(); let base = match src { ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(), @@ -831,7 +817,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> { _ => unreachable!(), }; - let div = unsafe { c.clk_gpout_div(self.gpout.number()).read() }; + let div = c.clk_gpout_div(self.gpout.number()).read(); let int = if div.int() == 0 { 65536 } else { div.int() } as u64; let frac = div.frac() as u64; @@ -842,12 +828,10 @@ impl<'d, T: GpoutPin> Gpout<'d, T> { impl<'d, T: GpoutPin> Drop for Gpout<'d, T> { fn drop(&mut self) { self.disable(); - unsafe { - self.gpout - .io() - .ctrl() - .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); - } + self.gpout + .io() + .ctrl() + .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0)); } } @@ -864,7 +848,7 @@ impl RoscRng { let mut acc = 0; for _ in 0..u8::BITS { acc <<= 1; - acc |= unsafe { random_reg.read().randombit() as u8 }; + acc |= random_reg.read().randombit() as u8; } acc } diff --git a/embassy-rp/src/critical_section_impl.rs b/embassy-rp/src/critical_section_impl.rs index ce284c85..d233e6fa 100644 --- a/embassy-rp/src/critical_section_impl.rs +++ b/embassy-rp/src/critical_section_impl.rs @@ -103,14 +103,11 @@ where /// Try to claim the spinlock. Will return `Some(Self)` if the lock is obtained, and `None` if the lock is /// already in use somewhere else. pub fn try_claim() -> Option { - // Safety: We're only reading from this register - unsafe { - let lock = pac::SIO.spinlock(N).read(); - if lock > 0 { - Some(Self(core::marker::PhantomData)) - } else { - None - } + let lock = pac::SIO.spinlock(N).read(); + if lock > 0 { + Some(Self(core::marker::PhantomData)) + } else { + None } } @@ -120,10 +117,8 @@ where /// /// Only call this function if you hold the spin-lock. pub unsafe fn release() { - unsafe { - // Write (any value): release the lock - pac::SIO.spinlock(N).write_value(1); - } + // Write (any value): release the lock + pac::SIO.spinlock(N).write_value(1); } } diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 25819f03..1a458778 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -14,7 +14,7 @@ use crate::{interrupt, pac, peripherals}; #[cfg(feature = "rt")] #[interrupt] -unsafe fn DMA_IRQ_0() { +fn DMA_IRQ_0() { let ints0 = pac::DMA.ints0().read().ints0(); for channel in 0..CHANNEL_COUNT { let ctrl_trig = pac::DMA.ch(channel).ctrl_trig().read(); @@ -128,28 +128,26 @@ fn copy_inner<'a, C: Channel>( ) -> Transfer<'a, C> { into_ref!(ch); - unsafe { - let p = ch.regs(); + let p = ch.regs(); - p.read_addr().write_value(from as u32); - p.write_addr().write_value(to as u32); - p.trans_count().write_value(len as u32); + p.read_addr().write_value(from as u32); + p.write_addr().write_value(to as u32); + p.trans_count().write_value(len as u32); - compiler_fence(Ordering::SeqCst); + compiler_fence(Ordering::SeqCst); - p.ctrl_trig().write(|w| { - // TODO: Add all DREQ options to pac vals::TreqSel, and use - // `set_treq:sel` - w.0 = ((dreq as u32) & 0x3f) << 15usize; - w.set_data_size(data_size); - w.set_incr_read(incr_read); - w.set_incr_write(incr_write); - w.set_chain_to(ch.number()); - w.set_en(true); - }); + p.ctrl_trig().write(|w| { + // TODO: Add all DREQ options to pac vals::TreqSel, and use + // `set_treq:sel` + w.0 = ((dreq as u32) & 0x3f) << 15usize; + w.set_data_size(data_size); + w.set_incr_read(incr_read); + w.set_incr_write(incr_write); + w.set_chain_to(ch.number()); + w.set_en(true); + }); - compiler_fence(Ordering::SeqCst); - } + compiler_fence(Ordering::SeqCst); Transfer::new(ch) } @@ -169,12 +167,10 @@ impl<'a, C: Channel> Transfer<'a, C> { impl<'a, C: Channel> Drop for Transfer<'a, C> { fn drop(&mut self) { let p = self.channel.regs(); - unsafe { - pac::DMA - .chan_abort() - .modify(|m| m.set_chan_abort(1 << self.channel.number())); - while p.ctrl_trig().read().busy() {} - } + pac::DMA + .chan_abort() + .modify(|m| m.set_chan_abort(1 << self.channel.number())); + while p.ctrl_trig().read().busy() {} } } @@ -186,7 +182,7 @@ impl<'a, C: Channel> Future for Transfer<'a, C> { // calls to wake will deregister the waker. CHANNEL_WAKERS[self.channel.number() as usize].register(cx.waker()); - if unsafe { self.channel.regs().ctrl_trig().read().busy() } { + if self.channel.regs().ctrl_trig().read().busy() { Poll::Pending } else { Poll::Ready(()) diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 5d928aba..96d2d454 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -167,7 +167,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { /// - DMA must not access flash memory unsafe fn in_ram(&mut self, operation: impl FnOnce()) -> Result<(), Error> { // Make sure we're running on CORE0 - let core_id: u32 = unsafe { pac::SIO.cpuid().read() }; + let core_id: u32 = pac::SIO.cpuid().read(); if core_id != 0 { return Err(Error::InvalidCore); } diff --git a/embassy-rp/src/float/div.rs b/embassy-rp/src/float/div.rs index 094dec44..aff0dcb0 100644 --- a/embassy-rp/src/float/div.rs +++ b/embassy-rp/src/float/div.rs @@ -17,45 +17,43 @@ where { let sio = rp_pac::SIO; - unsafe { - // Since we can't save the signed-ness of the calculation, we have to make - // sure that there's at least an 8 cycle delay before we read the result. - // The Pico SDK ensures this by using a 6 cycle push and two 1 cycle reads. - // Since we can't be sure the Rust implementation will optimize to the same, - // just use an explicit wait. - while !sio.div().csr().read().ready() {} + // Since we can't save the signed-ness of the calculation, we have to make + // sure that there's at least an 8 cycle delay before we read the result. + // The Pico SDK ensures this by using a 6 cycle push and two 1 cycle reads. + // Since we can't be sure the Rust implementation will optimize to the same, + // just use an explicit wait. + while !sio.div().csr().read().ready() {} - // Read the quotient last, since that's what clears the dirty flag - let dividend = sio.div().udividend().read(); - let divisor = sio.div().udivisor().read(); - let remainder = sio.div().remainder().read(); - let quotient = sio.div().quotient().read(); + // Read the quotient last, since that's what clears the dirty flag + let dividend = sio.div().udividend().read(); + let divisor = sio.div().udivisor().read(); + let remainder = sio.div().remainder().read(); + let quotient = sio.div().quotient().read(); - // If we get interrupted here (before a write sets the DIRTY flag) its fine, since - // we have the full state, so the interruptor doesn't have to restore it. Once the - // write happens and the DIRTY flag is set, the interruptor becomes responsible for - // restoring our state. - let result = f(); + // If we get interrupted here (before a write sets the DIRTY flag) its fine, since + // we have the full state, so the interruptor doesn't have to restore it. Once the + // write happens and the DIRTY flag is set, the interruptor becomes responsible for + // restoring our state. + let result = f(); - // If we are interrupted here, then the interruptor will start an incorrect calculation - // using a wrong divisor, but we'll restore the divisor and result ourselves correctly. - // This sets DIRTY, so any interruptor will save the state. - sio.div().udividend().write_value(dividend); - // If we are interrupted here, the the interruptor may start the calculation using - // incorrectly signed inputs, but we'll restore the result ourselves. - // This sets DIRTY, so any interruptor will save the state. - sio.div().udivisor().write_value(divisor); - // If we are interrupted here, the interruptor will have restored everything but the - // quotient may be wrongly signed. If the calculation started by the above writes is - // still ongoing it is stopped, so it won't replace the result we're restoring. - // DIRTY and READY set, but only DIRTY matters to make the interruptor save the state. - sio.div().remainder().write_value(remainder); - // State fully restored after the quotient write. This sets both DIRTY and READY, so - // whatever we may have interrupted can read the result. - sio.div().quotient().write_value(quotient); + // If we are interrupted here, then the interruptor will start an incorrect calculation + // using a wrong divisor, but we'll restore the divisor and result ourselves correctly. + // This sets DIRTY, so any interruptor will save the state. + sio.div().udividend().write_value(dividend); + // If we are interrupted here, the the interruptor may start the calculation using + // incorrectly signed inputs, but we'll restore the result ourselves. + // This sets DIRTY, so any interruptor will save the state. + sio.div().udivisor().write_value(divisor); + // If we are interrupted here, the interruptor will have restored everything but the + // quotient may be wrongly signed. If the calculation started by the above writes is + // still ongoing it is stopped, so it won't replace the result we're restoring. + // DIRTY and READY set, but only DIRTY matters to make the interruptor save the state. + sio.div().remainder().write_value(remainder); + // State fully restored after the quotient write. This sets both DIRTY and READY, so + // whatever we may have interrupted can read the result. + sio.div().quotient().write_value(quotient); - result - } + result } fn save_divider(f: F) -> R @@ -63,7 +61,7 @@ where F: FnOnce() -> R, { let sio = rp_pac::SIO; - if unsafe { !sio.div().csr().read().dirty() } { + if !sio.div().csr().read().dirty() { // Not dirty, so nothing is waiting for the calculation. So we can just // issue it directly without a save/restore. f() diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 66faa248..ce0d0255 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -144,7 +144,7 @@ pub(crate) unsafe fn init() { #[cfg(feature = "rt")] #[interrupt] -unsafe fn IO_IRQ_BANK0() { +fn IO_IRQ_BANK0() { let cpu = SIO.cpuid().read() as usize; // There are two sets of interrupt registers, one for cpu0 and one for cpu1 // and here we are selecting the set that belongs to the currently executing @@ -185,46 +185,44 @@ struct InputFuture<'a, T: Pin> { impl<'d, T: Pin> InputFuture<'d, T> { pub fn new(pin: impl Peripheral

+ 'd, level: InterruptTrigger) -> Self { into_ref!(pin); - unsafe { - let pin_group = (pin.pin() % 8) as usize; - // first, clear the INTR register bits. without this INTR will still - // contain reports of previous edges, causing the IRQ to fire early - // on stale state. clearing these means that we can only detect edges - // that occur *after* the clear happened, but since both this and the - // alternative are fundamentally racy it's probably fine. - // (the alternative being checking the current level and waiting for - // its inverse, but that requires reading the current level and thus - // missing anything that happened before the level was read.) - pac::IO_BANK0.intr(pin.pin() as usize / 8).write(|w| { - w.set_edge_high(pin_group, true); - w.set_edge_low(pin_group, true); - }); + let pin_group = (pin.pin() % 8) as usize; + // first, clear the INTR register bits. without this INTR will still + // contain reports of previous edges, causing the IRQ to fire early + // on stale state. clearing these means that we can only detect edges + // that occur *after* the clear happened, but since both this and the + // alternative are fundamentally racy it's probably fine. + // (the alternative being checking the current level and waiting for + // its inverse, but that requires reading the current level and thus + // missing anything that happened before the level was read.) + pac::IO_BANK0.intr(pin.pin() as usize / 8).write(|w| { + w.set_edge_high(pin_group, true); + w.set_edge_low(pin_group, true); + }); - // Each INTR register is divided into 8 groups, one group for each - // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, - // and EGDE_HIGH. - pin.int_proc() - .inte((pin.pin() / 8) as usize) - .write_set(|w| match level { - InterruptTrigger::LevelHigh => { - trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin()); - w.set_level_high(pin_group, true); - } - InterruptTrigger::LevelLow => { - w.set_level_low(pin_group, true); - } - InterruptTrigger::EdgeHigh => { - w.set_edge_high(pin_group, true); - } - InterruptTrigger::EdgeLow => { - w.set_edge_low(pin_group, true); - } - InterruptTrigger::AnyEdge => { - w.set_edge_high(pin_group, true); - w.set_edge_low(pin_group, true); - } - }); - } + // Each INTR register is divided into 8 groups, one group for each + // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, + // and EGDE_HIGH. + pin.int_proc() + .inte((pin.pin() / 8) as usize) + .write_set(|w| match level { + InterruptTrigger::LevelHigh => { + trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin()); + w.set_level_high(pin_group, true); + } + InterruptTrigger::LevelLow => { + w.set_level_low(pin_group, true); + } + InterruptTrigger::EdgeHigh => { + w.set_edge_high(pin_group, true); + } + InterruptTrigger::EdgeLow => { + w.set_edge_low(pin_group, true); + } + InterruptTrigger::AnyEdge => { + w.set_edge_high(pin_group, true); + w.set_edge_low(pin_group, true); + } + }); Self { pin, level } } @@ -242,7 +240,7 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> { // then we want to access the interrupt enable register for our // pin (there are 4 of these PROC0_INTE0, PROC0_INTE1, PROC0_INTE2, and // PROC0_INTE3 per cpu). - let inte: pac::io::regs::Int = unsafe { self.pin.int_proc().inte((self.pin.pin() / 8) as usize).read() }; + let inte: pac::io::regs::Int = self.pin.int_proc().inte((self.pin.pin() / 8) as usize).read(); // The register is divided into groups of four, one group for // each pin. Each group consists of four trigger levels LEVEL_LOW, // LEVEL_HIGH, EDGE_LOW, and EDGE_HIGH for each pin. @@ -449,15 +447,13 @@ impl<'d, T: Pin> Flex<'d, T> { pub fn new(pin: impl Peripheral

+ 'd) -> Self { into_ref!(pin); - unsafe { - pin.pad_ctrl().write(|w| { - w.set_ie(true); - }); + pin.pad_ctrl().write(|w| { + w.set_ie(true); + }); - pin.io().ctrl().write(|w| { - w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::SIO_0.0); - }); - } + pin.io().ctrl().write(|w| { + w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::SIO_0.0); + }); Self { pin } } @@ -470,43 +466,37 @@ impl<'d, T: Pin> Flex<'d, T> { /// Set the pin's pull. #[inline] pub fn set_pull(&mut self, pull: Pull) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_ie(true); - let (pu, pd) = match pull { - Pull::Up => (true, false), - Pull::Down => (false, true), - Pull::None => (false, false), - }; - w.set_pue(pu); - w.set_pde(pd); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_ie(true); + let (pu, pd) = match pull { + Pull::Up => (true, false), + Pull::Down => (false, true), + Pull::None => (false, false), + }; + w.set_pue(pu); + w.set_pde(pd); + }); } /// Set the pin's drive strength. #[inline] pub fn set_drive_strength(&mut self, strength: Drive) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_drive(match strength { - Drive::_2mA => pac::pads::vals::Drive::_2MA, - Drive::_4mA => pac::pads::vals::Drive::_4MA, - Drive::_8mA => pac::pads::vals::Drive::_8MA, - Drive::_12mA => pac::pads::vals::Drive::_12MA, - }); + self.pin.pad_ctrl().modify(|w| { + w.set_drive(match strength { + Drive::_2mA => pac::pads::vals::Drive::_2MA, + Drive::_4mA => pac::pads::vals::Drive::_4MA, + Drive::_8mA => pac::pads::vals::Drive::_8MA, + Drive::_12mA => pac::pads::vals::Drive::_12MA, }); - } + }); } // Set the pin's slew rate. #[inline] pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_slewfast(slew_rate == SlewRate::Fast); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_slewfast(slew_rate == SlewRate::Fast); + }); } /// Put the pin into input mode. @@ -514,7 +504,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// The pull setting is left unchanged. #[inline] pub fn set_as_input(&mut self) { - unsafe { self.pin.sio_oe().value_clr().write_value(self.bit()) } + self.pin.sio_oe().value_clr().write_value(self.bit()) } /// Put the pin into output mode. @@ -523,17 +513,17 @@ impl<'d, T: Pin> Flex<'d, T> { /// at a specific level, call `set_high`/`set_low` on the pin first. #[inline] pub fn set_as_output(&mut self) { - unsafe { self.pin.sio_oe().value_set().write_value(self.bit()) } + self.pin.sio_oe().value_set().write_value(self.bit()) } #[inline] fn is_set_as_output(&self) -> bool { - unsafe { (self.pin.sio_oe().value().read() & self.bit()) != 0 } + (self.pin.sio_oe().value().read() & self.bit()) != 0 } #[inline] pub fn toggle_set_as_output(&mut self) { - unsafe { self.pin.sio_oe().value_xor().write_value(self.bit()) } + self.pin.sio_oe().value_xor().write_value(self.bit()) } #[inline] @@ -543,7 +533,7 @@ impl<'d, T: Pin> Flex<'d, T> { #[inline] pub fn is_low(&self) -> bool { - unsafe { self.pin.sio_in().read() & self.bit() == 0 } + self.pin.sio_in().read() & self.bit() == 0 } /// Returns current pin level @@ -555,13 +545,13 @@ impl<'d, T: Pin> Flex<'d, T> { /// Set the output as high. #[inline] pub fn set_high(&mut self) { - unsafe { self.pin.sio_out().value_set().write_value(self.bit()) } + self.pin.sio_out().value_set().write_value(self.bit()) } /// Set the output as low. #[inline] pub fn set_low(&mut self) { - unsafe { self.pin.sio_out().value_clr().write_value(self.bit()) } + self.pin.sio_out().value_clr().write_value(self.bit()) } /// Set the output level. @@ -576,7 +566,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// Is the output level high? #[inline] pub fn is_set_high(&self) -> bool { - unsafe { (self.pin.sio_out().value().read() & self.bit()) == 0 } + (self.pin.sio_out().value().read() & self.bit()) == 0 } /// Is the output level low? @@ -594,7 +584,7 @@ impl<'d, T: Pin> Flex<'d, T> { /// Toggle pin output #[inline] pub fn toggle(&mut self) { - unsafe { self.pin.sio_out().value_xor().write_value(self.bit()) } + self.pin.sio_out().value_xor().write_value(self.bit()) } #[inline] @@ -626,12 +616,10 @@ impl<'d, T: Pin> Flex<'d, T> { impl<'d, T: Pin> Drop for Flex<'d, T> { #[inline] fn drop(&mut self) { - unsafe { - self.pin.pad_ctrl().write(|_| {}); - self.pin.io().ctrl().write(|w| { - w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0); - }); - } + self.pin.pad_ctrl().write(|_| {}); + self.pin.io().ctrl().write(|w| { + w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0); + }); } } @@ -688,7 +676,7 @@ pub(crate) mod sealed { Bank::Bank0 => crate::pac::IO_BANK0, Bank::Qspi => crate::pac::IO_QSPI, }; - let proc = unsafe { SIO.cpuid().read() }; + let proc = SIO.cpuid().read(); io_block.int_proc(proc as _) } } diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index ce9a082a..791c6455 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -85,7 +85,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let r = T::regs(); // mask everything initially - unsafe { r.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)) } + r.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; @@ -135,13 +135,11 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let last = remaining_queue == 0; batch += 1; - unsafe { - p.ic_data_cmd().write(|w| { - w.set_restart(restart && remaining_queue == buffer.len() - 1); - w.set_stop(last && send_stop); - w.set_cmd(true); - }); - } + p.ic_data_cmd().write(|w| { + w.set_restart(restart && remaining_queue == buffer.len() - 1); + w.set_stop(last && send_stop); + w.set_cmd(true); + }); } // We've either run out of txfifo or just plain finished setting up @@ -161,7 +159,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { Poll::Pending } }, - |_me| unsafe { + |_me| { // Set the read threshold to the number of bytes we're // expecting so we don't get spurious interrupts. p.ic_rx_tl().write(|w| w.set_rx_tl(batch - 1)); @@ -185,7 +183,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let rxbytes = (rxfifo as usize).min(remaining); let received = buffer.len() - remaining; for b in &mut buffer[received..received + rxbytes] { - *b = unsafe { p.ic_data_cmd().read().dat() }; + *b = p.ic_data_cmd().read().dat(); } remaining -= rxbytes; } @@ -211,13 +209,11 @@ impl<'d, T: Instance> I2c<'d, T, Async> { if let Some(byte) = bytes.next() { let last = bytes.peek().is_none(); - unsafe { - p.ic_data_cmd().write(|w| { - w.set_stop(last && send_stop); - w.set_cmd(false); - w.set_dat(byte); - }); - } + p.ic_data_cmd().write(|w| { + w.set_stop(last && send_stop); + w.set_cmd(false); + w.set_dat(byte); + }); } else { break 'xmit Ok(()); } @@ -235,7 +231,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { Poll::Pending } }, - |_me| unsafe { + |_me| { // Set tx "free" threshold a little high so that we get // woken before the fifo completely drains to minimize // transfer stalls. @@ -267,7 +263,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { let had_abort2 = self .wait_on( - |me| unsafe { + |me| { // We could see an abort while processing fifo backlog, // so handle it here. let abort = me.read_and_clear_abort_reason(); @@ -279,7 +275,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { Poll::Pending } }, - |_me| unsafe { + |_me| { p.ic_intr_mask().modify(|w| { w.set_m_stop_det(true); w.set_m_tx_abrt(true); @@ -287,9 +283,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> { }, ) .await; - unsafe { - p.ic_clr_stop_det().read(); - } + p.ic_clr_stop_det().read(); had_abort.and(had_abort2) } else { @@ -336,95 +330,93 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { let p = T::regs(); - unsafe { - let reset = T::reset(); - crate::reset::reset(reset); - crate::reset::unreset_wait(reset); + let reset = T::reset(); + crate::reset::reset(reset); + crate::reset::unreset_wait(reset); - p.ic_enable().write(|w| w.set_enable(false)); + p.ic_enable().write(|w| w.set_enable(false)); - // Select controller mode & speed - p.ic_con().modify(|w| { - // Always use "fast" mode (<= 400 kHz, works fine for standard - // mode too) - w.set_speed(i2c::vals::Speed::FAST); - w.set_master_mode(true); - w.set_ic_slave_disable(true); - w.set_ic_restart_en(true); - w.set_tx_empty_ctrl(true); - }); + // Select controller mode & speed + p.ic_con().modify(|w| { + // Always use "fast" mode (<= 400 kHz, works fine for standard + // mode too) + w.set_speed(i2c::vals::Speed::FAST); + w.set_master_mode(true); + w.set_ic_slave_disable(true); + w.set_ic_restart_en(true); + w.set_tx_empty_ctrl(true); + }); - // Set FIFO watermarks to 1 to make things simpler. This is encoded - // by a register value of 0. - p.ic_tx_tl().write(|w| w.set_tx_tl(0)); - p.ic_rx_tl().write(|w| w.set_rx_tl(0)); + // Set FIFO watermarks to 1 to make things simpler. This is encoded + // by a register value of 0. + p.ic_tx_tl().write(|w| w.set_tx_tl(0)); + p.ic_rx_tl().write(|w| w.set_rx_tl(0)); - // Configure SCL & SDA pins - scl.io().ctrl().write(|w| w.set_funcsel(3)); - sda.io().ctrl().write(|w| w.set_funcsel(3)); + // Configure SCL & SDA pins + scl.io().ctrl().write(|w| w.set_funcsel(3)); + sda.io().ctrl().write(|w| w.set_funcsel(3)); - scl.pad_ctrl().write(|w| { - w.set_schmitt(true); - w.set_ie(true); - w.set_od(false); - w.set_pue(true); - w.set_pde(false); - }); - sda.pad_ctrl().write(|w| { - w.set_schmitt(true); - w.set_ie(true); - w.set_od(false); - w.set_pue(true); - w.set_pde(false); - }); + scl.pad_ctrl().write(|w| { + w.set_schmitt(true); + w.set_ie(true); + w.set_od(false); + w.set_pue(true); + w.set_pde(false); + }); + sda.pad_ctrl().write(|w| { + w.set_schmitt(true); + w.set_ie(true); + w.set_od(false); + w.set_pue(true); + w.set_pde(false); + }); - // Configure baudrate + // Configure baudrate - // There are some subtleties to I2C timing which we are completely - // ignoring here See: - // https://github.com/raspberrypi/pico-sdk/blob/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7/src/rp2_common/hardware_i2c/i2c.c#L69 - let clk_base = crate::clocks::clk_peri_freq(); + // There are some subtleties to I2C timing which we are completely + // ignoring here See: + // https://github.com/raspberrypi/pico-sdk/blob/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7/src/rp2_common/hardware_i2c/i2c.c#L69 + let clk_base = crate::clocks::clk_peri_freq(); - let period = (clk_base + config.frequency / 2) / config.frequency; - let lcnt = period * 3 / 5; // spend 3/5 (60%) of the period low - let hcnt = period - lcnt; // and 2/5 (40%) of the period high + let period = (clk_base + config.frequency / 2) / config.frequency; + let lcnt = period * 3 / 5; // spend 3/5 (60%) of the period low + let hcnt = period - lcnt; // and 2/5 (40%) of the period high - // Check for out-of-range divisors: - assert!(hcnt <= 0xffff); - assert!(lcnt <= 0xffff); - assert!(hcnt >= 8); - assert!(lcnt >= 8); + // Check for out-of-range divisors: + assert!(hcnt <= 0xffff); + assert!(lcnt <= 0xffff); + assert!(hcnt >= 8); + assert!(lcnt >= 8); - // Per I2C-bus specification a device in standard or fast mode must - // internally provide a hold time of at least 300ns for the SDA - // signal to bridge the undefined region of the falling edge of SCL. - // A smaller hold time of 120ns is used for fast mode plus. - let sda_tx_hold_count = if config.frequency < 1_000_000 { - // sda_tx_hold_count = clk_base [cycles/s] * 300ns * (1s / - // 1e9ns) Reduce 300/1e9 to 3/1e7 to avoid numbers that don't - // fit in uint. Add 1 to avoid division truncation. - ((clk_base * 3) / 10_000_000) + 1 - } else { - // fast mode plus requires a clk_base > 32MHz - assert!(clk_base >= 32_000_000); + // Per I2C-bus specification a device in standard or fast mode must + // internally provide a hold time of at least 300ns for the SDA + // signal to bridge the undefined region of the falling edge of SCL. + // A smaller hold time of 120ns is used for fast mode plus. + let sda_tx_hold_count = if config.frequency < 1_000_000 { + // sda_tx_hold_count = clk_base [cycles/s] * 300ns * (1s / + // 1e9ns) Reduce 300/1e9 to 3/1e7 to avoid numbers that don't + // fit in uint. Add 1 to avoid division truncation. + ((clk_base * 3) / 10_000_000) + 1 + } else { + // fast mode plus requires a clk_base > 32MHz + assert!(clk_base >= 32_000_000); - // sda_tx_hold_count = clk_base [cycles/s] * 120ns * (1s / - // 1e9ns) Reduce 120/1e9 to 3/25e6 to avoid numbers that don't - // fit in uint. Add 1 to avoid division truncation. - ((clk_base * 3) / 25_000_000) + 1 - }; - assert!(sda_tx_hold_count <= lcnt - 2); + // sda_tx_hold_count = clk_base [cycles/s] * 120ns * (1s / + // 1e9ns) Reduce 120/1e9 to 3/25e6 to avoid numbers that don't + // fit in uint. Add 1 to avoid division truncation. + ((clk_base * 3) / 25_000_000) + 1 + }; + assert!(sda_tx_hold_count <= lcnt - 2); - p.ic_fs_scl_hcnt().write(|w| w.set_ic_fs_scl_hcnt(hcnt as u16)); - p.ic_fs_scl_lcnt().write(|w| w.set_ic_fs_scl_lcnt(lcnt as u16)); - p.ic_fs_spklen() - .write(|w| w.set_ic_fs_spklen(if lcnt < 16 { 1 } else { (lcnt / 16) as u8 })); - p.ic_sda_hold() - .modify(|w| w.set_ic_sda_tx_hold(sda_tx_hold_count as u16)); + p.ic_fs_scl_hcnt().write(|w| w.set_ic_fs_scl_hcnt(hcnt as u16)); + p.ic_fs_scl_lcnt().write(|w| w.set_ic_fs_scl_lcnt(lcnt as u16)); + p.ic_fs_spklen() + .write(|w| w.set_ic_fs_spklen(if lcnt < 16 { 1 } else { (lcnt / 16) as u8 })); + p.ic_sda_hold() + .modify(|w| w.set_ic_sda_tx_hold(sda_tx_hold_count as u16)); - // Enable I2C block - p.ic_enable().write(|w| w.set_enable(true)); - } + // Enable I2C block + p.ic_enable().write(|w| w.set_enable(true)); Self { phantom: PhantomData } } @@ -439,11 +431,9 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { } let p = T::regs(); - unsafe { - p.ic_enable().write(|w| w.set_enable(false)); - p.ic_tar().write(|w| w.set_ic_tar(addr)); - p.ic_enable().write(|w| w.set_enable(true)); - } + p.ic_enable().write(|w| w.set_enable(false)); + p.ic_tar().write(|w| w.set_ic_tar(addr)); + p.ic_enable().write(|w| w.set_enable(true)); Ok(()) } @@ -455,40 +445,38 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { #[inline] fn tx_fifo_capacity() -> u8 { let p = T::regs(); - unsafe { FIFO_SIZE - p.ic_txflr().read().txflr() } + FIFO_SIZE - p.ic_txflr().read().txflr() } #[inline] fn rx_fifo_len() -> u8 { let p = T::regs(); - unsafe { p.ic_rxflr().read().rxflr() } + p.ic_rxflr().read().rxflr() } fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> { let p = T::regs(); - unsafe { - let abort_reason = p.ic_tx_abrt_source().read(); - if abort_reason.0 != 0 { - // Note clearing the abort flag also clears the reason, and this - // instance of flag is clear-on-read! Note also the - // IC_CLR_TX_ABRT register always reads as 0. - p.ic_clr_tx_abrt().read(); + let abort_reason = p.ic_tx_abrt_source().read(); + if abort_reason.0 != 0 { + // Note clearing the abort flag also clears the reason, and this + // instance of flag is clear-on-read! Note also the + // IC_CLR_TX_ABRT register always reads as 0. + p.ic_clr_tx_abrt().read(); - let reason = if abort_reason.abrt_7b_addr_noack() - | abort_reason.abrt_10addr1_noack() - | abort_reason.abrt_10addr2_noack() - { - AbortReason::NoAcknowledge - } else if abort_reason.arb_lost() { - AbortReason::ArbitrationLoss - } else { - AbortReason::Other(abort_reason.0) - }; - - Err(Error::Abort(reason)) + let reason = if abort_reason.abrt_7b_addr_noack() + | abort_reason.abrt_10addr1_noack() + | abort_reason.abrt_10addr2_noack() + { + AbortReason::NoAcknowledge + } else if abort_reason.arb_lost() { + AbortReason::ArbitrationLoss } else { - Ok(()) - } + AbortReason::Other(abort_reason.0) + }; + + Err(Error::Abort(reason)) + } else { + Ok(()) } } @@ -503,24 +491,21 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { let first = i == 0; let last = i == lastindex; - // NOTE(unsafe) We have &mut self - unsafe { - // wait until there is space in the FIFO to write the next byte - while Self::tx_fifo_full() {} + // wait until there is space in the FIFO to write the next byte + while Self::tx_fifo_full() {} - p.ic_data_cmd().write(|w| { - w.set_restart(restart && first); - w.set_stop(send_stop && last); + p.ic_data_cmd().write(|w| { + w.set_restart(restart && first); + w.set_stop(send_stop && last); - w.set_cmd(true); - }); + w.set_cmd(true); + }); - while Self::rx_fifo_len() == 0 { - self.read_and_clear_abort_reason()?; - } - - *byte = p.ic_data_cmd().read().dat(); + while Self::rx_fifo_len() == 0 { + self.read_and_clear_abort_reason()?; } + + *byte = p.ic_data_cmd().read().dat(); } Ok(()) @@ -536,36 +521,33 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { for (i, byte) in write.iter().enumerate() { let last = i == write.len() - 1; - // NOTE(unsafe) We have &mut self - unsafe { - p.ic_data_cmd().write(|w| { - w.set_stop(send_stop && last); - w.set_dat(*byte); - }); + p.ic_data_cmd().write(|w| { + w.set_stop(send_stop && last); + w.set_dat(*byte); + }); - // Wait until the transmission of the address/data from the - // internal shift register has completed. For this to function - // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The - // TX_EMPTY_CTRL flag was set in i2c_init. - while !p.ic_raw_intr_stat().read().tx_empty() {} + // Wait until the transmission of the address/data from the + // internal shift register has completed. For this to function + // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The + // TX_EMPTY_CTRL flag was set in i2c_init. + while !p.ic_raw_intr_stat().read().tx_empty() {} - let abort_reason = self.read_and_clear_abort_reason(); + let abort_reason = self.read_and_clear_abort_reason(); - if abort_reason.is_err() || (send_stop && last) { - // If the transaction was aborted or if it completed - // successfully wait until the STOP condition has occurred. + if abort_reason.is_err() || (send_stop && last) { + // If the transaction was aborted or if it completed + // successfully wait until the STOP condition has occurred. - while !p.ic_raw_intr_stat().read().stop_det() {} + while !p.ic_raw_intr_stat().read().stop_det() {} - p.ic_clr_stop_det().read().clr_stop_det(); - } - - // Note the hardware issues a STOP automatically on an abort - // condition. Note also the hardware clears RX FIFO as well as - // TX on abort, ecause we set hwparam - // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0. - abort_reason?; + p.ic_clr_stop_det().read().clr_stop_det(); } + + // Note the hardware issues a STOP automatically on an abort + // condition. Note also the hardware clears RX FIFO as well as + // TX on abort, ecause we set hwparam + // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0. + abort_reason?; } Ok(()) } diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index d6f73219..4fd3cb46 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -261,33 +261,39 @@ pub fn init(config: config::Config) -> Peripherals { /// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. trait RegExt { - unsafe fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R; - unsafe fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R; - unsafe fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R; + fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R; + fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R; + fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R; } impl RegExt for pac::common::Reg { - unsafe fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R { + fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R { let mut val = Default::default(); let res = f(&mut val); - let ptr = (self.ptr() as *mut u8).add(0x1000) as *mut T; - ptr.write_volatile(val); + unsafe { + let ptr = (self.as_ptr() as *mut u8).add(0x1000) as *mut T; + ptr.write_volatile(val); + } res } - unsafe fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R { + fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R { let mut val = Default::default(); let res = f(&mut val); - let ptr = (self.ptr() as *mut u8).add(0x2000) as *mut T; - ptr.write_volatile(val); + unsafe { + let ptr = (self.as_ptr() as *mut u8).add(0x2000) as *mut T; + ptr.write_volatile(val); + } res } - unsafe fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R { + fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R { let mut val = Default::default(); let res = f(&mut val); - let ptr = (self.ptr() as *mut u8).add(0x3000) as *mut T; - ptr.write_volatile(val); + unsafe { + let ptr = (self.as_ptr() as *mut u8).add(0x3000) as *mut T; + ptr.write_volatile(val); + } res } } diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index 2a7e4822..468e8470 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -163,14 +163,12 @@ where } // Reset the core - unsafe { - let psm = pac::PSM; - psm.frce_off().modify(|w| w.set_proc1(true)); - while !psm.frce_off().read().proc1() { - cortex_m::asm::nop(); - } - psm.frce_off().modify(|w| w.set_proc1(false)); + let psm = pac::PSM; + psm.frce_off().modify(|w| w.set_proc1(true)); + while !psm.frce_off().read().proc1() { + cortex_m::asm::nop(); } + psm.frce_off().modify(|w| w.set_proc1(false)); // The ARM AAPCS ABI requires 8-byte stack alignment. // #[align] on `struct Stack` ensures the bottom is aligned, but the top could still be @@ -270,14 +268,12 @@ pub fn resume_core1() { // Push a value to the inter-core FIFO, block until space is available #[inline(always)] fn fifo_write(value: u32) { - unsafe { - let sio = pac::SIO; - // Wait for the FIFO to have enough space - while !sio.fifo().st().read().rdy() { - cortex_m::asm::nop(); - } - sio.fifo().wr().write_value(value); + let sio = pac::SIO; + // Wait for the FIFO to have enough space + while !sio.fifo().st().read().rdy() { + cortex_m::asm::nop(); } + sio.fifo().wr().write_value(value); // Fire off an event to the other core. // This is required as the other core may be `wfe` (waiting for event) cortex_m::asm::sev(); @@ -286,38 +282,32 @@ fn fifo_write(value: u32) { // Pop a value from inter-core FIFO, block until available #[inline(always)] fn fifo_read() -> u32 { - unsafe { - let sio = pac::SIO; - // Wait until FIFO has data - while !sio.fifo().st().read().vld() { - cortex_m::asm::nop(); - } - sio.fifo().rd().read() + let sio = pac::SIO; + // Wait until FIFO has data + while !sio.fifo().st().read().vld() { + cortex_m::asm::nop(); } + sio.fifo().rd().read() } // Pop a value from inter-core FIFO, `wfe` until available #[inline(always)] #[allow(unused)] fn fifo_read_wfe() -> u32 { - unsafe { - let sio = pac::SIO; - // Wait until FIFO has data - while !sio.fifo().st().read().vld() { - cortex_m::asm::wfe(); - } - sio.fifo().rd().read() + let sio = pac::SIO; + // Wait until FIFO has data + while !sio.fifo().st().read().vld() { + cortex_m::asm::wfe(); } + sio.fifo().rd().read() } // Drain inter-core FIFO #[inline(always)] fn fifo_drain() { - unsafe { - let sio = pac::SIO; - while sio.fifo().st().read().vld() { - let _ = sio.fifo().rd().read(); - } + let sio = pac::SIO; + while sio.fifo().st().read().vld() { + let _ = sio.fifo().rd().read(); } } diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 0fa3bd77..1b36e0a5 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -87,7 +87,7 @@ const SMIRQ_MASK: u32 = 1 << 8; #[cfg(feature = "rt")] #[interrupt] -unsafe fn PIO0_IRQ_0() { +fn PIO0_IRQ_0() { use crate::pac; let ints = pac::PIO0.irqs(0).ints().read().0; for bit in 0..12 { @@ -100,7 +100,7 @@ unsafe fn PIO0_IRQ_0() { #[cfg(feature = "rt")] #[interrupt] -unsafe fn PIO1_IRQ_0() { +fn PIO1_IRQ_0() { use crate::pac; let ints = pac::PIO1.irqs(0).ints().read().0; for bit in 0..12 { @@ -145,11 +145,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI Poll::Ready(()) } else { WAKERS[PIO::PIO_NO as usize].fifo_out()[SM].register(cx.waker()); - unsafe { - PIO::PIO.irqs(0).inte().write_set(|m| { - m.0 = TXNFULL_MASK << SM; - }); - } + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = TXNFULL_MASK << SM; + }); // debug!("Pending"); Poll::Pending } @@ -158,11 +156,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoOutFuture<'a, 'd, PIO, SM> { fn drop(&mut self) { - unsafe { - PIO::PIO.irqs(0).inte().write_clear(|m| { - m.0 = TXNFULL_MASK << SM; - }); - } + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = TXNFULL_MASK << SM; + }); } } @@ -186,11 +182,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO Poll::Ready(v) } else { WAKERS[PIO::PIO_NO as usize].fifo_in()[SM].register(cx.waker()); - unsafe { - PIO::PIO.irqs(0).inte().write_set(|m| { - m.0 = RXNEMPTY_MASK << SM; - }); - } + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = RXNEMPTY_MASK << SM; + }); //debug!("Pending"); Poll::Pending } @@ -199,11 +193,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoInFuture<'a, 'd, PIO, SM> { fn drop(&mut self) { - unsafe { - PIO::PIO.irqs(0).inte().write_clear(|m| { - m.0 = RXNEMPTY_MASK << SM; - }); - } + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = RXNEMPTY_MASK << SM; + }); } } @@ -220,30 +212,24 @@ impl<'a, 'd, PIO: Instance> Future for IrqFuture<'a, 'd, PIO> { //debug!("Poll {},{}", PIO::PIO_NO, SM); // Check if IRQ flag is already set - if unsafe { PIO::PIO.irq().read().0 & (1 << self.irq_no) != 0 } { - unsafe { - PIO::PIO.irq().write(|m| m.0 = 1 << self.irq_no); - } + if PIO::PIO.irq().read().0 & (1 << self.irq_no) != 0 { + PIO::PIO.irq().write(|m| m.0 = 1 << self.irq_no); return Poll::Ready(()); } WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker()); - unsafe { - PIO::PIO.irqs(0).inte().write_set(|m| { - m.0 = SMIRQ_MASK << self.irq_no; - }); - } + PIO::PIO.irqs(0).inte().write_set(|m| { + m.0 = SMIRQ_MASK << self.irq_no; + }); Poll::Pending } } impl<'a, 'd, PIO: Instance> Drop for IrqFuture<'a, 'd, PIO> { fn drop(&mut self) { - unsafe { - PIO::PIO.irqs(0).inte().write_clear(|m| { - m.0 = SMIRQ_MASK << self.irq_no; - }); - } + PIO::PIO.irqs(0).inte().write_clear(|m| { + m.0 = SMIRQ_MASK << self.irq_no; + }); } } @@ -256,57 +242,47 @@ impl<'l, PIO: Instance> Pin<'l, PIO> { /// Set the pin's drive strength. #[inline] pub fn set_drive_strength(&mut self, strength: Drive) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_drive(match strength { - Drive::_2mA => pac::pads::vals::Drive::_2MA, - Drive::_4mA => pac::pads::vals::Drive::_4MA, - Drive::_8mA => pac::pads::vals::Drive::_8MA, - Drive::_12mA => pac::pads::vals::Drive::_12MA, - }); + self.pin.pad_ctrl().modify(|w| { + w.set_drive(match strength { + Drive::_2mA => pac::pads::vals::Drive::_2MA, + Drive::_4mA => pac::pads::vals::Drive::_4MA, + Drive::_8mA => pac::pads::vals::Drive::_8MA, + Drive::_12mA => pac::pads::vals::Drive::_12MA, }); - } + }); } // Set the pin's slew rate. #[inline] pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_slewfast(slew_rate == SlewRate::Fast); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_slewfast(slew_rate == SlewRate::Fast); + }); } /// Set the pin's pull. #[inline] pub fn set_pull(&mut self, pull: Pull) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_pue(pull == Pull::Up); - w.set_pde(pull == Pull::Down); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_pue(pull == Pull::Up); + w.set_pde(pull == Pull::Down); + }); } /// Set the pin's schmitt trigger. #[inline] pub fn set_schmitt(&mut self, enable: bool) { - unsafe { - self.pin.pad_ctrl().modify(|w| { - w.set_schmitt(enable); - }); - } + self.pin.pad_ctrl().modify(|w| { + w.set_schmitt(enable); + }); } pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) { let mask = 1 << self.pin(); - unsafe { - if bypass { - PIO::PIO.input_sync_bypass().write_set(|w| *w = mask); - } else { - PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask); - } + if bypass { + PIO::PIO.input_sync_bypass().write_set(|w| *w = mask); + } else { + PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask); } } @@ -321,41 +297,37 @@ pub struct StateMachineRx<'d, PIO: Instance, const SM: usize> { impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { pub fn empty(&self) -> bool { - unsafe { PIO::PIO.fstat().read().rxempty() & (1u8 << SM) != 0 } + PIO::PIO.fstat().read().rxempty() & (1u8 << SM) != 0 } pub fn full(&self) -> bool { - unsafe { PIO::PIO.fstat().read().rxfull() & (1u8 << SM) != 0 } + PIO::PIO.fstat().read().rxfull() & (1u8 << SM) != 0 } pub fn level(&self) -> u8 { - unsafe { (PIO::PIO.flevel().read().0 >> (SM * 8 + 4)) as u8 & 0x0f } + (PIO::PIO.flevel().read().0 >> (SM * 8 + 4)) as u8 & 0x0f } pub fn stalled(&self) -> bool { - unsafe { - let fdebug = PIO::PIO.fdebug(); - let ret = fdebug.read().rxstall() & (1 << SM) != 0; - if ret { - fdebug.write(|w| w.set_rxstall(1 << SM)); - } - ret + let fdebug = PIO::PIO.fdebug(); + let ret = fdebug.read().rxstall() & (1 << SM) != 0; + if ret { + fdebug.write(|w| w.set_rxstall(1 << SM)); } + ret } pub fn underflowed(&self) -> bool { - unsafe { - let fdebug = PIO::PIO.fdebug(); - let ret = fdebug.read().rxunder() & (1 << SM) != 0; - if ret { - fdebug.write(|w| w.set_rxunder(1 << SM)); - } - ret + let fdebug = PIO::PIO.fdebug(); + let ret = fdebug.read().rxunder() & (1 << SM) != 0; + if ret { + fdebug.write(|w| w.set_rxunder(1 << SM)); } + ret } pub fn pull(&mut self) -> u32 { - unsafe { PIO::PIO.rxf(SM).read() } + PIO::PIO.rxf(SM).read() } pub fn try_pull(&mut self) -> Option { @@ -374,24 +346,22 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { ch: PeripheralRef<'a, C>, data: &'a mut [W], ) -> Transfer<'a, C> { - unsafe { - let pio_no = PIO::PIO_NO; - let p = ch.regs(); - p.write_addr().write_value(data.as_ptr() as u32); - p.read_addr().write_value(PIO::PIO.rxf(SM).ptr() as u32); - p.trans_count().write_value(data.len() as u32); - compiler_fence(Ordering::SeqCst); - p.ctrl_trig().write(|w| { - // Set RX DREQ for this statemachine - w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8 + 4)); - w.set_data_size(W::size()); - w.set_chain_to(ch.number()); - w.set_incr_read(false); - w.set_incr_write(true); - w.set_en(true); - }); - compiler_fence(Ordering::SeqCst); - } + let pio_no = PIO::PIO_NO; + let p = ch.regs(); + p.write_addr().write_value(data.as_ptr() as u32); + p.read_addr().write_value(PIO::PIO.rxf(SM).as_ptr() as u32); + p.trans_count().write_value(data.len() as u32); + compiler_fence(Ordering::SeqCst); + p.ctrl_trig().write(|w| { + // Set RX DREQ for this statemachine + w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8 + 4)); + w.set_data_size(W::size()); + w.set_chain_to(ch.number()); + w.set_incr_read(false); + w.set_incr_write(true); + w.set_en(true); + }); + compiler_fence(Ordering::SeqCst); Transfer::new(ch) } } @@ -402,42 +372,36 @@ pub struct StateMachineTx<'d, PIO: Instance, const SM: usize> { impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { pub fn empty(&self) -> bool { - unsafe { PIO::PIO.fstat().read().txempty() & (1u8 << SM) != 0 } + PIO::PIO.fstat().read().txempty() & (1u8 << SM) != 0 } pub fn full(&self) -> bool { - unsafe { PIO::PIO.fstat().read().txfull() & (1u8 << SM) != 0 } + PIO::PIO.fstat().read().txfull() & (1u8 << SM) != 0 } pub fn level(&self) -> u8 { - unsafe { (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f } + (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f } pub fn stalled(&self) -> bool { - unsafe { - let fdebug = PIO::PIO.fdebug(); - let ret = fdebug.read().txstall() & (1 << SM) != 0; - if ret { - fdebug.write(|w| w.set_txstall(1 << SM)); - } - ret + let fdebug = PIO::PIO.fdebug(); + let ret = fdebug.read().txstall() & (1 << SM) != 0; + if ret { + fdebug.write(|w| w.set_txstall(1 << SM)); } + ret } pub fn overflowed(&self) -> bool { - unsafe { - let fdebug = PIO::PIO.fdebug(); - let ret = fdebug.read().txover() & (1 << SM) != 0; - if ret { - fdebug.write(|w| w.set_txover(1 << SM)); - } - ret + let fdebug = PIO::PIO.fdebug(); + let ret = fdebug.read().txover() & (1 << SM) != 0; + if ret { + fdebug.write(|w| w.set_txover(1 << SM)); } + ret } pub fn push(&mut self, v: u32) { - unsafe { - PIO::PIO.txf(SM).write_value(v); - } + PIO::PIO.txf(SM).write_value(v); } pub fn try_push(&mut self, v: u32) -> bool { @@ -453,24 +417,22 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { } pub fn dma_push<'a, C: Channel, W: Word>(&'a mut self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> { - unsafe { - let pio_no = PIO::PIO_NO; - let p = ch.regs(); - p.read_addr().write_value(data.as_ptr() as u32); - p.write_addr().write_value(PIO::PIO.txf(SM).ptr() as u32); - p.trans_count().write_value(data.len() as u32); - compiler_fence(Ordering::SeqCst); - p.ctrl_trig().write(|w| { - // Set TX DREQ for this statemachine - w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8)); - w.set_data_size(W::size()); - w.set_chain_to(ch.number()); - w.set_incr_read(true); - w.set_incr_write(false); - w.set_en(true); - }); - compiler_fence(Ordering::SeqCst); - } + let pio_no = PIO::PIO_NO; + let p = ch.regs(); + p.read_addr().write_value(data.as_ptr() as u32); + p.write_addr().write_value(PIO::PIO.txf(SM).as_ptr() as u32); + p.trans_count().write_value(data.len() as u32); + compiler_fence(Ordering::SeqCst); + p.ctrl_trig().write(|w| { + // Set TX DREQ for this statemachine + w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8)); + w.set_data_size(W::size()); + w.set_chain_to(ch.number()); + w.set_incr_read(true); + w.set_incr_write(false); + w.set_en(true); + }); + compiler_fence(Ordering::SeqCst); Transfer::new(ch) } } @@ -482,9 +444,7 @@ pub struct StateMachine<'d, PIO: Instance, const SM: usize> { impl<'d, PIO: Instance, const SM: usize> Drop for StateMachine<'d, PIO, SM> { fn drop(&mut self) { - unsafe { - PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(1 << SM)); - } + PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(1 << SM)); on_pio_drop::(); } } @@ -647,45 +607,43 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { assert!(config.shift_in.threshold <= 32, "shift_in.threshold must be <= 32"); assert!(config.shift_out.threshold <= 32, "shift_out.threshold must be <= 32"); let sm = Self::this_sm(); - unsafe { - sm.clkdiv().write(|w| w.0 = config.clock_divider.to_bits() << 8); - sm.execctrl().write(|w| { - w.set_side_en(config.exec.side_en); - w.set_side_pindir(config.exec.side_pindir); - w.set_jmp_pin(config.exec.jmp_pin); - w.set_out_en_sel(config.out_en_sel); - w.set_inline_out_en(config.inline_out_en); - w.set_out_sticky(config.out_sticky); - w.set_wrap_top(config.exec.wrap_top); - w.set_wrap_bottom(config.exec.wrap_bottom); - w.set_status_sel(match config.status_sel { - StatusSource::TxFifoLevel => SmExecctrlStatusSel::TXLEVEL, - StatusSource::RxFifoLevel => SmExecctrlStatusSel::RXLEVEL, - }); - w.set_status_n(config.status_n); + sm.clkdiv().write(|w| w.0 = config.clock_divider.to_bits() << 8); + sm.execctrl().write(|w| { + w.set_side_en(config.exec.side_en); + w.set_side_pindir(config.exec.side_pindir); + w.set_jmp_pin(config.exec.jmp_pin); + w.set_out_en_sel(config.out_en_sel); + w.set_inline_out_en(config.inline_out_en); + w.set_out_sticky(config.out_sticky); + w.set_wrap_top(config.exec.wrap_top); + w.set_wrap_bottom(config.exec.wrap_bottom); + w.set_status_sel(match config.status_sel { + StatusSource::TxFifoLevel => SmExecctrlStatusSel::TXLEVEL, + StatusSource::RxFifoLevel => SmExecctrlStatusSel::RXLEVEL, }); - sm.shiftctrl().write(|w| { - w.set_fjoin_rx(config.fifo_join == FifoJoin::RxOnly); - w.set_fjoin_tx(config.fifo_join == FifoJoin::TxOnly); - w.set_pull_thresh(config.shift_out.threshold); - w.set_push_thresh(config.shift_in.threshold); - w.set_out_shiftdir(config.shift_out.direction == ShiftDirection::Right); - w.set_in_shiftdir(config.shift_in.direction == ShiftDirection::Right); - w.set_autopull(config.shift_out.auto_fill); - w.set_autopush(config.shift_in.auto_fill); - }); - sm.pinctrl().write(|w| { - w.set_sideset_count(config.pins.sideset_count); - w.set_set_count(config.pins.set_count); - w.set_out_count(config.pins.out_count); - w.set_in_base(config.pins.in_base); - w.set_sideset_base(config.pins.sideset_base); - w.set_set_base(config.pins.set_base); - w.set_out_base(config.pins.out_base); - }); - if let Some(origin) = config.origin { - pio_instr_util::exec_jmp(self, origin); - } + w.set_status_n(config.status_n); + }); + sm.shiftctrl().write(|w| { + w.set_fjoin_rx(config.fifo_join == FifoJoin::RxOnly); + w.set_fjoin_tx(config.fifo_join == FifoJoin::TxOnly); + w.set_pull_thresh(config.shift_out.threshold); + w.set_push_thresh(config.shift_in.threshold); + w.set_out_shiftdir(config.shift_out.direction == ShiftDirection::Right); + w.set_in_shiftdir(config.shift_in.direction == ShiftDirection::Right); + w.set_autopull(config.shift_out.auto_fill); + w.set_autopush(config.shift_in.auto_fill); + }); + sm.pinctrl().write(|w| { + w.set_sideset_count(config.pins.sideset_count); + w.set_set_count(config.pins.set_count); + w.set_out_count(config.pins.out_count); + w.set_in_base(config.pins.in_base); + w.set_sideset_base(config.pins.sideset_base); + w.set_set_base(config.pins.set_base); + w.set_out_base(config.pins.out_base); + }); + if let Some(origin) = config.origin { + unsafe { pio_instr_util::exec_jmp(self, origin) } } } @@ -696,45 +654,35 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { pub fn restart(&mut self) { let mask = 1u8 << SM; - unsafe { - PIO::PIO.ctrl().write_set(|w| w.set_sm_restart(mask)); - } + PIO::PIO.ctrl().write_set(|w| w.set_sm_restart(mask)); } pub fn set_enable(&mut self, enable: bool) { let mask = 1u8 << SM; - unsafe { - if enable { - PIO::PIO.ctrl().write_set(|w| w.set_sm_enable(mask)); - } else { - PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(mask)); - } + if enable { + PIO::PIO.ctrl().write_set(|w| w.set_sm_enable(mask)); + } else { + PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(mask)); } } pub fn is_enabled(&self) -> bool { - unsafe { PIO::PIO.ctrl().read().sm_enable() & (1u8 << SM) != 0 } + PIO::PIO.ctrl().read().sm_enable() & (1u8 << SM) != 0 } pub fn clkdiv_restart(&mut self) { let mask = 1u8 << SM; - unsafe { - PIO::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask)); - } + PIO::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask)); } fn with_paused(&mut self, f: impl FnOnce(&mut Self)) { let enabled = self.is_enabled(); self.set_enable(false); - let pincfg = unsafe { Self::this_sm().pinctrl().read() }; - let execcfg = unsafe { Self::this_sm().execctrl().read() }; - unsafe { - Self::this_sm().execctrl().write_clear(|w| w.set_out_sticky(true)); - } + let pincfg = Self::this_sm().pinctrl().read(); + let execcfg = Self::this_sm().execctrl().read(); + Self::this_sm().execctrl().write_clear(|w| w.set_out_sticky(true)); f(self); - unsafe { - Self::this_sm().pinctrl().write_value(pincfg); - Self::this_sm().execctrl().write_value(execcfg); - } + Self::this_sm().pinctrl().write_value(pincfg); + Self::this_sm().execctrl().write_value(execcfg); self.set_enable(enabled); } @@ -743,14 +691,12 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { pub fn set_pin_dirs(&mut self, dir: Direction, pins: &[&Pin<'d, PIO>]) { self.with_paused(|sm| { for pin in pins { - unsafe { - Self::this_sm().pinctrl().write(|w| { - w.set_set_base(pin.pin()); - w.set_set_count(1); - }); - // SET PINDIRS, (dir) - sm.exec_instr(0b111_00000_100_00000 | dir as u16); - } + Self::this_sm().pinctrl().write(|w| { + w.set_set_base(pin.pin()); + w.set_set_count(1); + }); + // SET PINDIRS, (dir) + unsafe { sm.exec_instr(0b111_00000_100_00000 | dir as u16) }; } }); } @@ -760,29 +706,25 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> { pub fn set_pins(&mut self, level: Level, pins: &[&Pin<'d, PIO>]) { self.with_paused(|sm| { for pin in pins { - unsafe { - Self::this_sm().pinctrl().write(|w| { - w.set_set_base(pin.pin()); - w.set_set_count(1); - }); - // SET PINS, (dir) - sm.exec_instr(0b111_00000_000_00000 | level as u16); - } + Self::this_sm().pinctrl().write(|w| { + w.set_set_base(pin.pin()); + w.set_set_count(1); + }); + // SET PINS, (dir) + unsafe { sm.exec_instr(0b111_00000_000_00000 | level as u16) }; } }); } pub fn clear_fifos(&mut self) { // Toggle FJOIN_RX to flush FIFOs - unsafe { - let shiftctrl = Self::this_sm().shiftctrl(); - shiftctrl.modify(|w| { - w.set_fjoin_rx(!w.fjoin_rx()); - }); - shiftctrl.modify(|w| { - w.set_fjoin_rx(!w.fjoin_rx()); - }); - } + let shiftctrl = Self::this_sm().shiftctrl(); + shiftctrl.modify(|w| { + w.set_fjoin_rx(!w.fjoin_rx()); + }); + shiftctrl.modify(|w| { + w.set_fjoin_rx(!w.fjoin_rx()); + }); } pub unsafe fn exec_instr(&mut self, instr: u16) { @@ -856,11 +798,9 @@ impl<'d, PIO: Instance> Common<'d, PIO> { if (self.instructions_used | used_mask) & mask != 0 { return Err(addr); } - unsafe { - PIO::PIO.instr_mem(addr).write(|w| { - w.set_instr_mem(instr); - }); - } + PIO::PIO.instr_mem(addr).write(|w| { + w.set_instr_mem(instr); + }); used_mask |= mask; } self.instructions_used |= used_mask; @@ -877,17 +817,15 @@ impl<'d, PIO: Instance> Common<'d, PIO> { } pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { - unsafe { - // this can interfere with per-pin bypass functions. splitting the - // modification is going to be fine since nothing that relies on - // it can reasonably run before we finish. - PIO::PIO.input_sync_bypass().write_set(|w| *w = mask & bypass); - PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass); - } + // this can interfere with per-pin bypass functions. splitting the + // modification is going to be fine since nothing that relies on + // it can reasonably run before we finish. + PIO::PIO.input_sync_bypass().write_set(|w| *w = mask & bypass); + PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass); } pub fn get_input_sync_bypass(&self) -> u32 { - unsafe { PIO::PIO.input_sync_bypass().read() } + PIO::PIO.input_sync_bypass().read() } /// Register a pin for PIO usage. Pins will be released from the PIO block @@ -896,9 +834,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> { /// of [`Pio`] do not keep pin registrations alive.** pub fn make_pio_pin(&mut self, pin: impl Peripheral

+ 'd) -> Pin<'d, PIO> { into_ref!(pin); - unsafe { - pin.io().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL.0)); - } + pin.io().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL.0)); // we can be relaxed about this because we're &mut here and nothing is cached PIO::state().used_pins.fetch_or(1 << pin.pin_bank(), Ordering::Relaxed); Pin { @@ -916,13 +852,11 @@ impl<'d, PIO: Instance> Common<'d, PIO> { _pio: PhantomData, }; f(&mut batch); - unsafe { - PIO::PIO.ctrl().modify(|w| { - w.set_clkdiv_restart(batch.clkdiv_restart); - w.set_sm_restart(batch.sm_restart); - w.set_sm_enable((w.sm_enable() & !batch.sm_enable_mask) | batch.sm_enable); - }); - } + PIO::PIO.ctrl().modify(|w| { + w.set_clkdiv_restart(batch.clkdiv_restart); + w.set_sm_restart(batch.sm_restart); + w.set_sm_enable((w.sm_enable() & !batch.sm_enable_mask) | batch.sm_enable); + }); } } @@ -974,11 +908,11 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> { } pub fn check_any(&self, irqs: u8) -> bool { - unsafe { PIO::PIO.irq().read().irq() & irqs != 0 } + PIO::PIO.irq().read().irq() & irqs != 0 } pub fn check_all(&self, irqs: u8) -> bool { - unsafe { PIO::PIO.irq().read().irq() & irqs == irqs } + PIO::PIO.irq().read().irq() & irqs == irqs } pub fn clear(&self, irq_no: usize) { @@ -987,7 +921,7 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> { } pub fn clear_all(&self, irqs: u8) { - unsafe { PIO::PIO.irq().write(|w| w.set_irq(irqs)) } + PIO::PIO.irq().write(|w| w.set_irq(irqs)) } pub fn set(&self, irq_no: usize) { @@ -996,7 +930,7 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> { } pub fn set_all(&self, irqs: u8) { - unsafe { PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs)) } + PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs)) } } @@ -1068,9 +1002,7 @@ fn on_pio_drop() { // we only have 30 pins. don't test the other two since gpio() asserts. for i in 0..30 { if used_pins & (1 << i) != 0 { - unsafe { - pac::IO_BANK0.gpio(i).ctrl().write(|w| w.set_funcsel(null)); - } + pac::IO_BANK0.gpio(i).ctrl().write(|w| w.set_funcsel(null)); } } } diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs index 0f9dcf47..20bb8844 100644 --- a/embassy-rp/src/pwm.rs +++ b/embassy-rp/src/pwm.rs @@ -71,20 +71,18 @@ impl<'d, T: Channel> Pwm<'d, T> { into_ref!(inner); let p = inner.regs(); - unsafe { - p.csr().modify(|w| { - w.set_divmode(divmode); - w.set_en(false); - }); - p.ctr().write(|w| w.0 = 0); - Self::configure(p, &config); + p.csr().modify(|w| { + w.set_divmode(divmode); + w.set_en(false); + }); + p.ctr().write(|w| w.0 = 0); + Self::configure(p, &config); - if let Some(pin) = &a { - pin.io().ctrl().write(|w| w.set_funcsel(4)); - } - if let Some(pin) = &b { - pin.io().ctrl().write(|w| w.set_funcsel(4)); - } + if let Some(pin) = &a { + pin.io().ctrl().write(|w| w.set_funcsel(4)); + } + if let Some(pin) = &b { + pin.io().ctrl().write(|w| w.set_funcsel(4)); } Self { inner, @@ -161,31 +159,29 @@ impl<'d, T: Channel> Pwm<'d, T> { panic!("Requested divider is too large"); } - unsafe { - p.div().write_value(ChDiv(config.divider.to_bits() as u32)); - p.cc().write(|w| { - w.set_a(config.compare_a); - w.set_b(config.compare_b); - }); - p.top().write(|w| w.set_top(config.top)); - p.csr().modify(|w| { - w.set_a_inv(config.invert_a); - w.set_b_inv(config.invert_b); - w.set_ph_correct(config.phase_correct); - w.set_en(config.enable); - }); - } + p.div().write_value(ChDiv(config.divider.to_bits() as u32)); + p.cc().write(|w| { + w.set_a(config.compare_a); + w.set_b(config.compare_b); + }); + p.top().write(|w| w.set_top(config.top)); + p.csr().modify(|w| { + w.set_a_inv(config.invert_a); + w.set_b_inv(config.invert_b); + w.set_ph_correct(config.phase_correct); + w.set_en(config.enable); + }); } #[inline] - pub unsafe fn phase_advance(&mut self) { + pub fn phase_advance(&mut self) { let p = self.inner.regs(); p.csr().write_set(|w| w.set_ph_adv(true)); while p.csr().read().ph_adv() {} } #[inline] - pub unsafe fn phase_retard(&mut self) { + pub fn phase_retard(&mut self) { let p = self.inner.regs(); p.csr().write_set(|w| w.set_ph_ret(true)); while p.csr().read().ph_ret() {} @@ -193,12 +189,12 @@ impl<'d, T: Channel> Pwm<'d, T> { #[inline] pub fn counter(&self) -> u16 { - unsafe { self.inner.regs().ctr().read().ctr() } + self.inner.regs().ctr().read().ctr() } #[inline] pub fn set_counter(&self, ctr: u16) { - unsafe { self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) } + self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) } #[inline] @@ -209,14 +205,12 @@ impl<'d, T: Channel> Pwm<'d, T> { #[inline] pub fn wrapped(&mut self) -> bool { - unsafe { pac::PWM.intr().read().0 & self.bit() != 0 } + pac::PWM.intr().read().0 & self.bit() != 0 } #[inline] pub fn clear_wrapped(&mut self) { - unsafe { - pac::PWM.intr().write_value(Intr(self.bit() as _)); - } + pac::PWM.intr().write_value(Intr(self.bit() as _)); } #[inline] @@ -237,26 +231,22 @@ impl PwmBatch { pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) { let mut en = PwmBatch(0); batch(&mut en); - unsafe { - if enabled { - pac::PWM.en().write_set(|w| w.0 = en.0); - } else { - pac::PWM.en().write_clear(|w| w.0 = en.0); - } + if enabled { + pac::PWM.en().write_set(|w| w.0 = en.0); + } else { + pac::PWM.en().write_clear(|w| w.0 = en.0); } } } impl<'d, T: Channel> Drop for Pwm<'d, T> { fn drop(&mut self) { - unsafe { - self.inner.regs().csr().write_clear(|w| w.set_en(false)); - if let Some(pin) = &self.pin_a { - pin.io().ctrl().write(|w| w.set_funcsel(31)); - } - if let Some(pin) = &self.pin_b { - pin.io().ctrl().write(|w| w.set_funcsel(31)); - } + self.inner.regs().csr().write_clear(|w| w.set_en(false)); + if let Some(pin) = &self.pin_a { + pin.io().ctrl().write(|w| w.set_funcsel(31)); + } + if let Some(pin) = &self.pin_b { + pin.io().ctrl().write(|w| w.set_funcsel(31)); } } } diff --git a/embassy-rp/src/reset.rs b/embassy-rp/src/reset.rs index edd47c22..70512fa1 100644 --- a/embassy-rp/src/reset.rs +++ b/embassy-rp/src/reset.rs @@ -4,11 +4,11 @@ use crate::pac; pub const ALL_PERIPHERALS: Peripherals = Peripherals(0x01ffffff); -pub unsafe fn reset(peris: Peripherals) { +pub(crate) fn reset(peris: Peripherals) { pac::RESETS.reset().write_value(peris); } -pub unsafe fn unreset_wait(peris: Peripherals) { +pub(crate) fn unreset_wait(peris: Peripherals) { // TODO use the "atomic clear" register version pac::RESETS.reset().modify(|v| *v = Peripherals(v.0 & !peris.0)); while ((!pac::RESETS.reset_done().read().0) & peris.0) != 0 {} diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index e1d886d4..b18f12fc 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs @@ -26,7 +26,7 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { into_ref!(inner); // Set the RTC divider - unsafe { inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)) }; + inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)); let mut result = Self { inner }; result.set_leap_year_check(true); // should be on by default, make sure this is the case. @@ -38,17 +38,14 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { /// /// Leap year checking is enabled by default. pub fn set_leap_year_check(&mut self, leap_year_check_enabled: bool) { - unsafe { - self.inner - .regs() - .ctrl() - .modify(|w| w.set_force_notleapyear(!leap_year_check_enabled)) - }; + self.inner.regs().ctrl().modify(|w| { + w.set_force_notleapyear(!leap_year_check_enabled); + }); } /// Checks to see if this RealTimeClock is running pub fn is_running(&self) -> bool { - unsafe { self.inner.regs().ctrl().read().rtc_active() } + self.inner.regs().ctrl().read().rtc_active() } /// Set the datetime to a new value. @@ -60,25 +57,23 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { self::datetime::validate_datetime(&t).map_err(RtcError::InvalidDateTime)?; // disable RTC while we configure it - unsafe { - self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); - while self.inner.regs().ctrl().read().rtc_active() { - core::hint::spin_loop(); - } + self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); + while self.inner.regs().ctrl().read().rtc_active() { + core::hint::spin_loop(); + } - self.inner.regs().setup_0().write(|w| { - self::datetime::write_setup_0(&t, w); - }); - self.inner.regs().setup_1().write(|w| { - self::datetime::write_setup_1(&t, w); - }); + self.inner.regs().setup_0().write(|w| { + self::datetime::write_setup_0(&t, w); + }); + self.inner.regs().setup_1().write(|w| { + self::datetime::write_setup_1(&t, w); + }); - // Load the new datetime and re-enable RTC - self.inner.regs().ctrl().write(|w| w.set_load(true)); - self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); - while !self.inner.regs().ctrl().read().rtc_active() { - core::hint::spin_loop(); - } + // Load the new datetime and re-enable RTC + self.inner.regs().ctrl().write(|w| w.set_load(true)); + self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); + while !self.inner.regs().ctrl().read().rtc_active() { + core::hint::spin_loop(); } Ok(()) } @@ -93,8 +88,8 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { return Err(RtcError::NotRunning); } - let rtc_0 = unsafe { self.inner.regs().rtc_0().read() }; - let rtc_1 = unsafe { self.inner.regs().rtc_1().read() }; + let rtc_0 = self.inner.regs().rtc_0().read(); + let rtc_1 = self.inner.regs().rtc_1().read(); self::datetime::datetime_from_registers(rtc_0, rtc_1).map_err(RtcError::InvalidDateTime) } @@ -103,12 +98,10 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { /// /// [`schedule_alarm`]: #method.schedule_alarm pub fn disable_alarm(&mut self) { - unsafe { - self.inner.regs().irq_setup_0().modify(|s| s.set_match_ena(false)); + self.inner.regs().irq_setup_0().modify(|s| s.set_match_ena(false)); - while self.inner.regs().irq_setup_0().read().match_active() { - core::hint::spin_loop(); - } + while self.inner.regs().irq_setup_0().read().match_active() { + core::hint::spin_loop(); } } @@ -132,21 +125,19 @@ impl<'d, T: Instance> RealTimeClock<'d, T> { pub fn schedule_alarm(&mut self, filter: DateTimeFilter) { self.disable_alarm(); - unsafe { - self.inner.regs().irq_setup_0().write(|w| { - filter.write_setup_0(w); - }); - self.inner.regs().irq_setup_1().write(|w| { - filter.write_setup_1(w); - }); + self.inner.regs().irq_setup_0().write(|w| { + filter.write_setup_0(w); + }); + self.inner.regs().irq_setup_1().write(|w| { + filter.write_setup_1(w); + }); - self.inner.regs().inte().modify(|w| w.set_rtc(true)); + self.inner.regs().inte().modify(|w| w.set_rtc(true)); - // Set the enable bit and check if it is set - self.inner.regs().irq_setup_0().modify(|w| w.set_match_ena(true)); - while !self.inner.regs().irq_setup_0().read().match_active() { - core::hint::spin_loop(); - } + // Set the enable bit and check if it is set + self.inner.regs().irq_setup_0().modify(|w| w.set_match_ena(true)); + while !self.inner.regs().irq_setup_0().read().match_active() { + core::hint::spin_loop(); } } diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index 7da21474..e817d074 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -79,39 +79,37 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { ) -> Self { into_ref!(inner); - unsafe { - let p = inner.regs(); - let (presc, postdiv) = calc_prescs(config.frequency); + let p = inner.regs(); + let (presc, postdiv) = calc_prescs(config.frequency); - p.cpsr().write(|w| w.set_cpsdvsr(presc)); - p.cr0().write(|w| { - w.set_dss(0b0111); // 8bit - w.set_spo(config.polarity == Polarity::IdleHigh); - w.set_sph(config.phase == Phase::CaptureOnSecondTransition); - w.set_scr(postdiv); - }); + p.cpsr().write(|w| w.set_cpsdvsr(presc)); + p.cr0().write(|w| { + w.set_dss(0b0111); // 8bit + w.set_spo(config.polarity == Polarity::IdleHigh); + w.set_sph(config.phase == Phase::CaptureOnSecondTransition); + w.set_scr(postdiv); + }); - // Always enable DREQ signals -- harmless if DMA is not listening - p.dmacr().write(|reg| { - reg.set_rxdmae(true); - reg.set_txdmae(true); - }); + // Always enable DREQ signals -- harmless if DMA is not listening + p.dmacr().write(|reg| { + reg.set_rxdmae(true); + reg.set_txdmae(true); + }); - // finally, enable. - p.cr1().write(|w| w.set_sse(true)); + // finally, enable. + p.cr1().write(|w| w.set_sse(true)); - if let Some(pin) = &clk { - pin.io().ctrl().write(|w| w.set_funcsel(1)); - } - if let Some(pin) = &mosi { - pin.io().ctrl().write(|w| w.set_funcsel(1)); - } - if let Some(pin) = &miso { - pin.io().ctrl().write(|w| w.set_funcsel(1)); - } - if let Some(pin) = &cs { - pin.io().ctrl().write(|w| w.set_funcsel(1)); - } + if let Some(pin) = &clk { + pin.io().ctrl().write(|w| w.set_funcsel(1)); + } + if let Some(pin) = &mosi { + pin.io().ctrl().write(|w| w.set_funcsel(1)); + } + if let Some(pin) = &miso { + pin.io().ctrl().write(|w| w.set_funcsel(1)); + } + if let Some(pin) = &cs { + pin.io().ctrl().write(|w| w.set_funcsel(1)); } Self { inner, @@ -122,60 +120,52 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { } pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - for &b in data { - while !p.sr().read().tnf() {} - p.dr().write(|w| w.set_data(b as _)); - while !p.sr().read().rne() {} - let _ = p.dr().read(); - } + let p = self.inner.regs(); + for &b in data { + while !p.sr().read().tnf() {} + p.dr().write(|w| w.set_data(b as _)); + while !p.sr().read().rne() {} + let _ = p.dr().read(); } self.flush()?; Ok(()) } pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - for b in data { - while !p.sr().read().tnf() {} - p.dr().write(|w| w.set_data(*b as _)); - while !p.sr().read().rne() {} - *b = p.dr().read().data() as u8; - } + let p = self.inner.regs(); + for b in data { + while !p.sr().read().tnf() {} + p.dr().write(|w| w.set_data(*b as _)); + while !p.sr().read().rne() {} + *b = p.dr().read().data() as u8; } self.flush()?; Ok(()) } pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - for b in data { - while !p.sr().read().tnf() {} - p.dr().write(|w| w.set_data(0)); - while !p.sr().read().rne() {} - *b = p.dr().read().data() as u8; - } + let p = self.inner.regs(); + for b in data { + while !p.sr().read().tnf() {} + p.dr().write(|w| w.set_data(0)); + while !p.sr().read().rne() {} + *b = p.dr().read().data() as u8; } self.flush()?; Ok(()) } pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - let len = read.len().max(write.len()); - for i in 0..len { - let wb = write.get(i).copied().unwrap_or(0); - while !p.sr().read().tnf() {} - p.dr().write(|w| w.set_data(wb as _)); - while !p.sr().read().rne() {} - let rb = p.dr().read().data() as u8; - if let Some(r) = read.get_mut(i) { - *r = rb; - } + let p = self.inner.regs(); + let len = read.len().max(write.len()); + for i in 0..len { + let wb = write.get(i).copied().unwrap_or(0); + while !p.sr().read().tnf() {} + p.dr().write(|w| w.set_data(wb as _)); + while !p.sr().read().rne() {} + let rb = p.dr().read().data() as u8; + if let Some(r) = read.get_mut(i) { + *r = rb; } } self.flush()?; @@ -183,29 +173,25 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> { } pub fn flush(&mut self) -> Result<(), Error> { - unsafe { - let p = self.inner.regs(); - while p.sr().read().bsy() {} - } + let p = self.inner.regs(); + while p.sr().read().bsy() {} Ok(()) } pub fn set_frequency(&mut self, freq: u32) { let (presc, postdiv) = calc_prescs(freq); let p = self.inner.regs(); - unsafe { - // disable - p.cr1().write(|w| w.set_sse(false)); + // disable + p.cr1().write(|w| w.set_sse(false)); - // change stuff - p.cpsr().write(|w| w.set_cpsdvsr(presc)); - p.cr0().modify(|w| { - w.set_scr(postdiv); - }); + // change stuff + p.cpsr().write(|w| w.set_cpsdvsr(presc)); + p.cr0().modify(|w| { + w.set_scr(postdiv); + }); - // enable - p.cr1().write(|w| w.set_sse(true)); - } + // enable + p.cr1().write(|w| w.set_sse(true)); } } @@ -337,21 +323,19 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let tx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::write(tx_ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) + crate::dma::write(tx_ch, buffer, self.inner.regs().dr().as_ptr() as *mut _, T::TX_DREQ) }; tx_transfer.await; let p = self.inner.regs(); - unsafe { - while p.sr().read().bsy() {} + while p.sr().read().bsy() {} - // clear RX FIFO contents to prevent stale reads - while p.sr().read().rne() { - let _: u16 = p.dr().read().data(); - } - // clear RX overrun interrupt - p.icr().write(|w| w.set_roric(true)); + // clear RX FIFO contents to prevent stale reads + while p.sr().read().rne() { + let _: u16 = p.dr().read().data(); } + // clear RX overrun interrupt + p.icr().write(|w| w.set_roric(true)); Ok(()) } @@ -363,14 +347,19 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let rx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) + crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, buffer, T::RX_DREQ) }; let tx_ch = self.tx_dma.as_mut().unwrap(); let tx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ) + crate::dma::write_repeated( + tx_ch, + self.inner.regs().dr().as_ptr() as *mut u8, + buffer.len(), + T::TX_DREQ, + ) }; join(tx_transfer, rx_transfer).await; Ok(()) @@ -394,7 +383,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let rx_transfer = unsafe { // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) + crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, rx_ptr, T::RX_DREQ) }; let mut tx_ch = self.tx_dma.as_mut().unwrap(); @@ -403,13 +392,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> { let tx_transfer = async { let p = self.inner.regs(); unsafe { - crate::dma::write(&mut tx_ch, tx_ptr, p.dr().ptr() as *mut _, T::TX_DREQ).await; + crate::dma::write(&mut tx_ch, tx_ptr, p.dr().as_ptr() as *mut _, T::TX_DREQ).await; if rx_len > tx_len { let write_bytes_len = rx_len - tx_len; // write dummy data // this will disable incrementation of the buffers - crate::dma::write_repeated(tx_ch, p.dr().ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await + crate::dma::write_repeated(tx_ch, p.dr().as_ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await } } }; @@ -418,16 +407,14 @@ impl<'d, T: Instance> Spi<'d, T, Async> { // if tx > rx we should clear any overflow of the FIFO SPI buffer if tx_len > rx_len { let p = self.inner.regs(); - unsafe { - while p.sr().read().bsy() {} + while p.sr().read().bsy() {} - // clear RX FIFO contents to prevent stale reads - while p.sr().read().rne() { - let _: u16 = p.dr().read().data(); - } - // clear RX overrun interrupt - p.icr().write(|w| w.set_roric(true)); + // clear RX FIFO contents to prevent stale reads + while p.sr().read().rne() { + let _: u16 = p.dr().read().data(); } + // clear RX overrun interrupt + p.icr().write(|w| w.set_roric(true)); } Ok(()) @@ -625,14 +612,12 @@ impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> { fn set_config(&mut self, config: &Self::Config) { let p = self.inner.regs(); let (presc, postdiv) = calc_prescs(config.frequency); - unsafe { - p.cpsr().write(|w| w.set_cpsdvsr(presc)); - p.cr0().write(|w| { - w.set_dss(0b0111); // 8bit - w.set_spo(config.polarity == Polarity::IdleHigh); - w.set_sph(config.phase == Phase::CaptureOnSecondTransition); - w.set_scr(postdiv); - }); - } + p.cpsr().write(|w| w.set_cpsdvsr(presc)); + p.cr0().write(|w| { + w.set_dss(0b0111); // 8bit + w.set_spo(config.polarity == Polarity::IdleHigh); + w.set_sph(config.phase == Phase::CaptureOnSecondTransition); + w.set_scr(postdiv); + }); } } diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs index ca8c96c0..faa8df03 100644 --- a/embassy-rp/src/timer.rs +++ b/embassy-rp/src/timer.rs @@ -34,13 +34,11 @@ embassy_time::time_driver_impl!(static DRIVER: TimerDriver = TimerDriver{ impl Driver for TimerDriver { fn now(&self) -> u64 { loop { - unsafe { - let hi = pac::TIMER.timerawh().read(); - let lo = pac::TIMER.timerawl().read(); - let hi2 = pac::TIMER.timerawh().read(); - if hi == hi2 { - return (hi as u64) << 32 | (lo as u64); - } + let hi = pac::TIMER.timerawh().read(); + let lo = pac::TIMER.timerawl().read(); + let hi2 = pac::TIMER.timerawh().read(); + if hi == hi2 { + return (hi as u64) << 32 | (lo as u64); } } } @@ -78,13 +76,13 @@ impl Driver for TimerDriver { // Note that we're not checking the high bits at all. This means the irq may fire early // if the alarm is more than 72 minutes (2^32 us) in the future. This is OK, since on irq fire // it is checked if the alarm time has passed. - unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; + pac::TIMER.alarm(n).write_value(timestamp as u32); let now = self.now(); if timestamp <= now { // If alarm timestamp has passed the alarm will not fire. // Disarm the alarm and return `false` to indicate that. - unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) } + pac::TIMER.armed().write(|w| w.set_armed(1 << n)); alarm.timestamp.set(u64::MAX); @@ -106,17 +104,17 @@ impl TimerDriver { } else { // Not elapsed, arm it again. // This can happen if it was set more than 2^32 us in the future. - unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; + pac::TIMER.alarm(n).write_value(timestamp as u32); } }); // clear the irq - unsafe { pac::TIMER.intr().write(|w| w.set_alarm(n, true)) } + pac::TIMER.intr().write(|w| w.set_alarm(n, true)); } fn trigger_alarm(&self, n: usize, cs: CriticalSection) { // disarm - unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) } + pac::TIMER.armed().write(|w| w.set_armed(1 << n)); let alarm = &self.alarms.borrow(cs)[n]; alarm.timestamp.set(u64::MAX); @@ -153,24 +151,24 @@ pub unsafe fn init() { #[cfg(feature = "rt")] #[interrupt] -unsafe fn TIMER_IRQ_0() { +fn TIMER_IRQ_0() { DRIVER.check_alarm(0) } #[cfg(feature = "rt")] #[interrupt] -unsafe fn TIMER_IRQ_1() { +fn TIMER_IRQ_1() { DRIVER.check_alarm(1) } #[cfg(feature = "rt")] #[interrupt] -unsafe fn TIMER_IRQ_2() { +fn TIMER_IRQ_2() { DRIVER.check_alarm(2) } #[cfg(feature = "rt")] #[interrupt] -unsafe fn TIMER_IRQ_3() { +fn TIMER_IRQ_3() { DRIVER.check_alarm(3) } diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index 6660d5dc..30eeb547 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs @@ -73,16 +73,14 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>( // we clear it after it happens. The downside is that the we manually have // to pend the ISR when we want data transmission to start. let regs = T::regs(); - unsafe { - regs.uartimsc().write(|w| { - w.set_rxim(true); - w.set_rtim(true); - w.set_txim(true); - }); + regs.uartimsc().write(|w| { + w.set_rxim(true); + w.set_rtim(true); + w.set_txim(true); + }); - T::Interrupt::unpend(); - T::Interrupt::enable(); - }; + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; } impl<'d, T: Instance> BufferedUart<'d, T> { @@ -247,12 +245,10 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> { // (Re-)Enable the interrupt to receive more data in case it was // disabled because the buffer was full or errors were detected. let regs = T::regs(); - unsafe { - regs.uartimsc().write_set(|w| { - w.set_rxim(true); - w.set_rtim(true); - }); - } + regs.uartimsc().write_set(|w| { + w.set_rxim(true); + w.set_rtim(true); + }); Poll::Ready(result) } @@ -299,12 +295,10 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> { // (Re-)Enable the interrupt to receive more data in case it was // disabled because the buffer was full or errors were detected. let regs = T::regs(); - unsafe { - regs.uartimsc().write_set(|w| { - w.set_rxim(true); - w.set_rtim(true); - }); - } + regs.uartimsc().write_set(|w| { + w.set_rxim(true); + w.set_rtim(true); + }); } } @@ -414,7 +408,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> { } pub fn busy(&self) -> bool { - unsafe { T::regs().uartfr().read().busy() } + T::regs().uartfr().read().busy() } /// Assert a break condition after waiting for the transmit buffers to empty, @@ -426,42 +420,35 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> { /// for the transmit fifo to empty, which may take a while on slow links. pub async fn send_break(&mut self, bits: u32) { let regs = T::regs(); - let bits = bits.max(unsafe { + let bits = bits.max({ let lcr = regs.uartlcr_h().read(); let width = lcr.wlen() as u32 + 5; let parity = lcr.pen() as u32; let stops = 1 + lcr.stp2() as u32; 2 * (1 + width + parity + stops) }); - let divx64 = unsafe { - ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32 - } as u64; + let divx64 = (((regs.uartibrd().read().baud_divint() as u32) << 6) + + regs.uartfbrd().read().baud_divfrac() as u32) as u64; let div_clk = clk_peri_freq() as u64 * 64; let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk; Self::flush().await.unwrap(); while self.busy() {} - unsafe { - regs.uartlcr_h().write_set(|w| w.set_brk(true)); - } + regs.uartlcr_h().write_set(|w| w.set_brk(true)); Timer::after(Duration::from_micros(wait_usecs)).await; - unsafe { - regs.uartlcr_h().write_clear(|w| w.set_brk(true)); - } + regs.uartlcr_h().write_clear(|w| w.set_brk(true)); } } impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { fn drop(&mut self) { let state = T::buffered_state(); - unsafe { - state.rx_buf.deinit(); + unsafe { state.rx_buf.deinit() } - // TX is inactive if the the buffer is not available. - // We can now unregister the interrupt handler - if state.tx_buf.len() == 0 { - T::Interrupt::disable(); - } + // TX is inactive if the the buffer is not available. + // We can now unregister the interrupt handler + if state.tx_buf.len() == 0 { + T::Interrupt::disable(); } } } @@ -469,14 +456,12 @@ impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> { fn drop(&mut self) { let state = T::buffered_state(); - unsafe { - state.tx_buf.deinit(); + unsafe { state.tx_buf.deinit() } - // RX is inactive if the the buffer is not available. - // We can now unregister the interrupt handler - if state.rx_buf.len() == 0 { - T::Interrupt::disable(); - } + // RX is inactive if the the buffer is not available. + // We can now unregister the interrupt handler + if state.rx_buf.len() == 0 { + T::Interrupt::disable(); } } } @@ -494,94 +479,92 @@ impl interrupt::typelevel::Handler for BufferedInterr let s = T::buffered_state(); - unsafe { - // Clear TX and error interrupt flags - // RX interrupt flags are cleared by reading from the FIFO. - let ris = r.uartris().read(); - r.uarticr().write(|w| { - w.set_txic(ris.txris()); - w.set_feic(ris.feris()); - w.set_peic(ris.peris()); - w.set_beic(ris.beris()); - w.set_oeic(ris.oeris()); - }); + // Clear TX and error interrupt flags + // RX interrupt flags are cleared by reading from the FIFO. + let ris = r.uartris().read(); + r.uarticr().write(|w| { + w.set_txic(ris.txris()); + w.set_feic(ris.feris()); + w.set_peic(ris.peris()); + w.set_beic(ris.beris()); + w.set_oeic(ris.oeris()); + }); - trace!("on_interrupt ris={:#X}", ris.0); + trace!("on_interrupt ris={:#X}", ris.0); - // Errors - if ris.feris() { - warn!("Framing error"); - } - if ris.peris() { - warn!("Parity error"); - } - if ris.beris() { - warn!("Break error"); - } - if ris.oeris() { - warn!("Overrun error"); - } - - // RX - let mut rx_writer = s.rx_buf.writer(); - let rx_buf = rx_writer.push_slice(); - let mut n_read = 0; - let mut error = false; - for rx_byte in rx_buf { - if r.uartfr().read().rxfe() { - break; - } - let dr = r.uartdr().read(); - if (dr.0 >> 8) != 0 { - s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed); - error = true; - // only fill the buffer with valid characters. the current character is fine - // if the error is an overrun, but if we add it to the buffer we'll report - // the overrun one character too late. drop it instead and pretend we were - // a bit slower at draining the rx fifo than we actually were. - // this is consistent with blocking uart error reporting. - break; - } - *rx_byte = dr.data(); - n_read += 1; - } - if n_read > 0 { - rx_writer.push_done(n_read); - s.rx_waker.wake(); - } else if error { - s.rx_waker.wake(); - } - // Disable any further RX interrupts when the buffer becomes full or - // errors have occurred. This lets us buffer additional errors in the - // fifo without needing more error storage locations, and most applications - // will want to do a full reset of their uart state anyway once an error - // has happened. - if s.rx_buf.is_full() || error { - r.uartimsc().write_clear(|w| { - w.set_rxim(true); - w.set_rtim(true); - }); - } - - // TX - let mut tx_reader = s.tx_buf.reader(); - let tx_buf = tx_reader.pop_slice(); - let mut n_written = 0; - for tx_byte in tx_buf.iter_mut() { - if r.uartfr().read().txff() { - break; - } - r.uartdr().write(|w| w.set_data(*tx_byte)); - n_written += 1; - } - if n_written > 0 { - tx_reader.pop_done(n_written); - s.tx_waker.wake(); - } - // The TX interrupt only triggers once when the FIFO threshold is - // crossed. No need to disable it when the buffer becomes empty - // as it does re-trigger anymore once we have cleared it. + // Errors + if ris.feris() { + warn!("Framing error"); } + if ris.peris() { + warn!("Parity error"); + } + if ris.beris() { + warn!("Break error"); + } + if ris.oeris() { + warn!("Overrun error"); + } + + // RX + let mut rx_writer = unsafe { s.rx_buf.writer() }; + let rx_buf = rx_writer.push_slice(); + let mut n_read = 0; + let mut error = false; + for rx_byte in rx_buf { + if r.uartfr().read().rxfe() { + break; + } + let dr = r.uartdr().read(); + if (dr.0 >> 8) != 0 { + s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed); + error = true; + // only fill the buffer with valid characters. the current character is fine + // if the error is an overrun, but if we add it to the buffer we'll report + // the overrun one character too late. drop it instead and pretend we were + // a bit slower at draining the rx fifo than we actually were. + // this is consistent with blocking uart error reporting. + break; + } + *rx_byte = dr.data(); + n_read += 1; + } + if n_read > 0 { + rx_writer.push_done(n_read); + s.rx_waker.wake(); + } else if error { + s.rx_waker.wake(); + } + // Disable any further RX interrupts when the buffer becomes full or + // errors have occurred. This lets us buffer additional errors in the + // fifo without needing more error storage locations, and most applications + // will want to do a full reset of their uart state anyway once an error + // has happened. + if s.rx_buf.is_full() || error { + r.uartimsc().write_clear(|w| { + w.set_rxim(true); + w.set_rtim(true); + }); + } + + // TX + let mut tx_reader = unsafe { s.tx_buf.reader() }; + let tx_buf = tx_reader.pop_slice(); + let mut n_written = 0; + for tx_byte in tx_buf.iter_mut() { + if r.uartfr().read().txff() { + break; + } + r.uartdr().write(|w| w.set_data(*tx_byte)); + n_written += 1; + } + if n_written > 0 { + tx_reader.pop_done(n_written); + s.tx_waker.wake(); + } + // The TX interrupt only triggers once when the FIFO threshold is + // crossed. No need to disable it when the buffer becomes empty + // as it does re-trigger anymore once we have cleared it. } } @@ -695,24 +678,22 @@ mod eh02 { fn read(&mut self) -> Result> { let r = T::regs(); - unsafe { - if r.uartfr().read().rxfe() { - return Err(nb::Error::WouldBlock); - } + if r.uartfr().read().rxfe() { + return Err(nb::Error::WouldBlock); + } - let dr = r.uartdr().read(); + let dr = r.uartdr().read(); - if dr.oe() { - Err(nb::Error::Other(Error::Overrun)) - } else if dr.be() { - Err(nb::Error::Other(Error::Break)) - } else if dr.pe() { - Err(nb::Error::Other(Error::Parity)) - } else if dr.fe() { - Err(nb::Error::Other(Error::Framing)) - } else { - Ok(dr.data()) - } + if dr.oe() { + Err(nb::Error::Other(Error::Overrun)) + } else if dr.be() { + Err(nb::Error::Other(Error::Break)) + } else if dr.pe() { + Err(nb::Error::Other(Error::Parity)) + } else if dr.fe() { + Err(nb::Error::Other(Error::Framing)) + } else { + Ok(dr.data()) } } } diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 5e3ae8a2..7b94bce5 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -146,23 +146,21 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { let r = T::regs(); - unsafe { - for &b in buffer { - while r.uartfr().read().txff() {} - r.uartdr().write(|w| w.set_data(b)); - } + for &b in buffer { + while r.uartfr().read().txff() {} + r.uartdr().write(|w| w.set_data(b)); } Ok(()) } pub fn blocking_flush(&mut self) -> Result<(), Error> { let r = T::regs(); - unsafe { while !r.uartfr().read().txfe() {} } + while !r.uartfr().read().txfe() {} Ok(()) } pub fn busy(&self) -> bool { - unsafe { T::regs().uartfr().read().busy() } + T::regs().uartfr().read().busy() } /// Assert a break condition after waiting for the transmit buffers to empty, @@ -174,28 +172,23 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { /// for the transmit fifo to empty, which may take a while on slow links. pub async fn send_break(&mut self, bits: u32) { let regs = T::regs(); - let bits = bits.max(unsafe { + let bits = bits.max({ let lcr = regs.uartlcr_h().read(); let width = lcr.wlen() as u32 + 5; let parity = lcr.pen() as u32; let stops = 1 + lcr.stp2() as u32; 2 * (1 + width + parity + stops) }); - let divx64 = unsafe { - ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32 - } as u64; + let divx64 = (((regs.uartibrd().read().baud_divint() as u32) << 6) + + regs.uartfbrd().read().baud_divfrac() as u32) as u64; let div_clk = clk_peri_freq() as u64 * 64; let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk; self.blocking_flush().unwrap(); while self.busy() {} - unsafe { - regs.uartlcr_h().write_set(|w| w.set_brk(true)); - } + regs.uartlcr_h().write_set(|w| w.set_brk(true)); Timer::after(Duration::from_micros(wait_usecs)).await; - unsafe { - regs.uartlcr_h().write_clear(|w| w.set_brk(true)); - } + regs.uartlcr_h().write_clear(|w| w.set_brk(true)); } } @@ -221,7 +214,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> { }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ) + crate::dma::write(ch, buffer, T::regs().uartdr().as_ptr() as *mut _, T::TX_DREQ) }; transfer.await; Ok(()) @@ -246,7 +239,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { debug_assert_eq!(has_irq, rx_dma.is_some()); if has_irq { // disable all error interrupts initially - unsafe { T::regs().uartimsc().write(|w| w.0 = 0) } + T::regs().uartimsc().write(|w| w.0 = 0); T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; } @@ -267,11 +260,11 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result { let r = T::regs(); for (i, b) in buffer.iter_mut().enumerate() { - if unsafe { r.uartfr().read().rxfe() } { + if r.uartfr().read().rxfe() { return Ok(i); } - let dr = unsafe { r.uartdr().read() }; + let dr = r.uartdr().read(); if dr.oe() { return Err(Error::Overrun); @@ -292,15 +285,13 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> { fn drop(&mut self) { if let Some(_) = self.rx_dma { - unsafe { - T::Interrupt::disable(); - // clear dma flags. irq handlers use these to disambiguate among themselves. - T::regs().uartdmacr().write_clear(|reg| { - reg.set_rxdmae(true); - reg.set_txdmae(true); - reg.set_dmaonerr(true); - }); - } + T::Interrupt::disable(); + // clear dma flags. irq handlers use these to disambiguate among themselves. + T::regs().uartdmacr().write_clear(|reg| { + reg.set_rxdmae(true); + reg.set_txdmae(true); + reg.set_dmaonerr(true); + }); } } } @@ -355,14 +346,12 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { // clear error flags before we drain the fifo. errors that have accumulated // in the flags will also be present in the fifo. T::dma_state().rx_errs.store(0, Ordering::Relaxed); - unsafe { - T::regs().uarticr().write(|w| { - w.set_oeic(true); - w.set_beic(true); - w.set_peic(true); - w.set_feic(true); - }); - } + T::regs().uarticr().write(|w| { + w.set_oeic(true); + w.set_beic(true); + w.set_peic(true); + w.set_feic(true); + }); // then drain the fifo. we need to read at most 32 bytes. errors that apply // to fifo bytes will be reported directly. @@ -379,20 +368,20 @@ impl<'d, T: Instance> UartRx<'d, T, Async> { // interrupt flags will have been raised, and those will be picked up immediately // by the interrupt handler. let ch = self.rx_dma.as_mut().unwrap(); + T::regs().uartimsc().write_set(|w| { + w.set_oeim(true); + w.set_beim(true); + w.set_peim(true); + w.set_feim(true); + }); + T::regs().uartdmacr().write_set(|reg| { + reg.set_rxdmae(true); + reg.set_dmaonerr(true); + }); let transfer = unsafe { - T::regs().uartimsc().write_set(|w| { - w.set_oeim(true); - w.set_beim(true); - w.set_peim(true); - w.set_feim(true); - }); - T::regs().uartdmacr().write_set(|reg| { - reg.set_rxdmae(true); - reg.set_dmaonerr(true); - }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ) + crate::dma::read(ch, T::regs().uartdr().as_ptr() as *const _, buffer, T::RX_DREQ) }; // wait for either the transfer to complete or an error to happen. @@ -575,81 +564,79 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> { config: Config, ) { let r = T::regs(); - unsafe { - if let Some(pin) = &tx { - pin.io().ctrl().write(|w| { - w.set_funcsel(2); - w.set_outover(if config.invert_tx { - Outover::INVERT - } else { - Outover::NORMAL - }); + if let Some(pin) = &tx { + pin.io().ctrl().write(|w| { + w.set_funcsel(2); + w.set_outover(if config.invert_tx { + Outover::INVERT + } else { + Outover::NORMAL }); - pin.pad_ctrl().write(|w| w.set_ie(true)); - } - if let Some(pin) = &rx { - pin.io().ctrl().write(|w| { - w.set_funcsel(2); - w.set_inover(if config.invert_rx { - Inover::INVERT - } else { - Inover::NORMAL - }); - }); - pin.pad_ctrl().write(|w| w.set_ie(true)); - } - if let Some(pin) = &cts { - pin.io().ctrl().write(|w| { - w.set_funcsel(2); - w.set_inover(if config.invert_cts { - Inover::INVERT - } else { - Inover::NORMAL - }); - }); - pin.pad_ctrl().write(|w| w.set_ie(true)); - } - if let Some(pin) = &rts { - pin.io().ctrl().write(|w| { - w.set_funcsel(2); - w.set_outover(if config.invert_rts { - Outover::INVERT - } else { - Outover::NORMAL - }); - }); - pin.pad_ctrl().write(|w| w.set_ie(true)); - } - - Self::set_baudrate_inner(config.baudrate); - - let (pen, eps) = match config.parity { - Parity::ParityNone => (false, false), - Parity::ParityOdd => (true, false), - Parity::ParityEven => (true, true), - }; - - r.uartlcr_h().write(|w| { - w.set_wlen(config.data_bits.bits()); - w.set_stp2(config.stop_bits == StopBits::STOP2); - w.set_pen(pen); - w.set_eps(eps); - w.set_fen(true); - }); - - r.uartifls().write(|w| { - w.set_rxiflsel(0b000); - w.set_txiflsel(0b000); - }); - - r.uartcr().write(|w| { - w.set_uarten(true); - w.set_rxe(true); - w.set_txe(true); - w.set_ctsen(cts.is_some()); - w.set_rtsen(rts.is_some()); }); + pin.pad_ctrl().write(|w| w.set_ie(true)); } + if let Some(pin) = &rx { + pin.io().ctrl().write(|w| { + w.set_funcsel(2); + w.set_inover(if config.invert_rx { + Inover::INVERT + } else { + Inover::NORMAL + }); + }); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + if let Some(pin) = &cts { + pin.io().ctrl().write(|w| { + w.set_funcsel(2); + w.set_inover(if config.invert_cts { + Inover::INVERT + } else { + Inover::NORMAL + }); + }); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + if let Some(pin) = &rts { + pin.io().ctrl().write(|w| { + w.set_funcsel(2); + w.set_outover(if config.invert_rts { + Outover::INVERT + } else { + Outover::NORMAL + }); + }); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + + Self::set_baudrate_inner(config.baudrate); + + let (pen, eps) = match config.parity { + Parity::ParityNone => (false, false), + Parity::ParityOdd => (true, false), + Parity::ParityEven => (true, true), + }; + + r.uartlcr_h().write(|w| { + w.set_wlen(config.data_bits.bits()); + w.set_stp2(config.stop_bits == StopBits::STOP2); + w.set_pen(pen); + w.set_eps(eps); + w.set_fen(true); + }); + + r.uartifls().write(|w| { + w.set_rxiflsel(0b000); + w.set_txiflsel(0b000); + }); + + r.uartcr().write(|w| { + w.set_uarten(true); + w.set_rxe(true); + w.set_txe(true); + w.set_ctsen(cts.is_some()); + w.set_rtsen(rts.is_some()); + }); } /// sets baudrate on runtime @@ -674,15 +661,13 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> { baud_fbrd = 0; } - unsafe { - // Load PL011's baud divisor registers - r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd)); - r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd)); + // Load PL011's baud divisor registers + r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd)); + r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd)); - // PL011 needs a (dummy) line control register write to latch in the - // divisors. We don't want to actually change LCR contents here. - r.uartlcr_h().modify(|_| {}); - } + // PL011 needs a (dummy) line control register write to latch in the + // divisors. We don't want to actually change LCR contents here. + r.uartlcr_h().modify(|_| {}); } } @@ -731,24 +716,22 @@ mod eh02 { type Error = Error; fn read(&mut self) -> Result> { let r = T::regs(); - unsafe { - if r.uartfr().read().rxfe() { - return Err(nb::Error::WouldBlock); - } + if r.uartfr().read().rxfe() { + return Err(nb::Error::WouldBlock); + } - let dr = r.uartdr().read(); + let dr = r.uartdr().read(); - if dr.oe() { - Err(nb::Error::Other(Error::Overrun)) - } else if dr.be() { - Err(nb::Error::Other(Error::Break)) - } else if dr.pe() { - Err(nb::Error::Other(Error::Parity)) - } else if dr.fe() { - Err(nb::Error::Other(Error::Framing)) - } else { - Ok(dr.data()) - } + if dr.oe() { + Err(nb::Error::Other(Error::Overrun)) + } else if dr.be() { + Err(nb::Error::Other(Error::Break)) + } else if dr.pe() { + Err(nb::Error::Other(Error::Parity)) + } else if dr.fe() { + Err(nb::Error::Other(Error::Framing)) + } else { + Ok(dr.data()) } } } @@ -758,22 +741,18 @@ mod eh02 { fn write(&mut self, word: u8) -> Result<(), nb::Error> { let r = T::regs(); - unsafe { - if r.uartfr().read().txff() { - return Err(nb::Error::WouldBlock); - } - - r.uartdr().write(|w| w.set_data(word)); + if r.uartfr().read().txff() { + return Err(nb::Error::WouldBlock); } + + r.uartdr().write(|w| w.set_data(word)); Ok(()) } fn flush(&mut self) -> Result<(), nb::Error> { let r = T::regs(); - unsafe { - if !r.uartfr().read().txfe() { - return Err(nb::Error::WouldBlock); - } + if !r.uartfr().read().txfe() { + return Err(nb::Error::WouldBlock); } Ok(()) } @@ -854,22 +833,20 @@ mod eh1 { impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> { fn read(&mut self) -> nb::Result { let r = T::regs(); - unsafe { - let dr = r.uartdr().read(); + let dr = r.uartdr().read(); - if dr.oe() { - Err(nb::Error::Other(Error::Overrun)) - } else if dr.be() { - Err(nb::Error::Other(Error::Break)) - } else if dr.pe() { - Err(nb::Error::Other(Error::Parity)) - } else if dr.fe() { - Err(nb::Error::Other(Error::Framing)) - } else if dr.fe() { - Ok(dr.data()) - } else { - Err(nb::Error::WouldBlock) - } + if dr.oe() { + Err(nb::Error::Other(Error::Overrun)) + } else if dr.be() { + Err(nb::Error::Other(Error::Break)) + } else if dr.pe() { + Err(nb::Error::Other(Error::Parity)) + } else if dr.fe() { + Err(nb::Error::Other(Error::Framing)) + } else if dr.fe() { + Ok(dr.data()) + } else { + Err(nb::Error::WouldBlock) } } } diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index 9fb0dfb7..1900ab41 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -39,7 +39,7 @@ impl crate::usb::Instance for peripherals::USB { const EP_COUNT: usize = 16; const EP_MEMORY_SIZE: usize = 4096; -const EP_MEMORY: *mut u8 = pac::USBCTRL_DPRAM.0; +const EP_MEMORY: *mut u8 = pac::USBCTRL_DPRAM.as_ptr() as *mut u8; const NEW_AW: AtomicWaker = AtomicWaker::new(); static BUS_WAKER: AtomicWaker = NEW_AW; @@ -111,7 +111,7 @@ impl<'d, T: Instance> Driver<'d, T> { let regs = T::regs(); unsafe { // zero fill regs - let p = regs.0 as *mut u32; + let p = regs.as_ptr() as *mut u32; for i in 0..0x9c / 4 { p.add(i).write_volatile(0) } @@ -121,20 +121,20 @@ impl<'d, T: Instance> Driver<'d, T> { for i in 0..0x100 / 4 { p.add(i).write_volatile(0) } - - regs.usb_muxing().write(|w| { - w.set_to_phy(true); - w.set_softcon(true); - }); - regs.usb_pwr().write(|w| { - w.set_vbus_detect(true); - w.set_vbus_detect_override_en(true); - }); - regs.main_ctrl().write(|w| { - w.set_controller_en(true); - }); } + regs.usb_muxing().write(|w| { + w.set_to_phy(true); + w.set_softcon(true); + }); + regs.usb_pwr().write(|w| { + w.set_vbus_detect(true); + w.set_vbus_detect_override_en(true); + }); + regs.main_ctrl().write(|w| { + w.set_controller_en(true); + }); + // Initialize the bus so that it signals that power is available BUS_WAKER.wake(); @@ -213,22 +213,18 @@ impl<'d, T: Instance> Driver<'d, T> { }; match D::dir() { - Direction::Out => unsafe { - T::dpram().ep_out_control(index - 1).write(|w| { - w.set_enable(false); - w.set_buffer_address(addr); - w.set_interrupt_per_buff(true); - w.set_endpoint_type(ep_type_reg); - }) - }, - Direction::In => unsafe { - T::dpram().ep_in_control(index - 1).write(|w| { - w.set_enable(false); - w.set_buffer_address(addr); - w.set_interrupt_per_buff(true); - w.set_endpoint_type(ep_type_reg); - }) - }, + Direction::Out => T::dpram().ep_out_control(index - 1).write(|w| { + w.set_enable(false); + w.set_buffer_address(addr); + w.set_interrupt_per_buff(true); + w.set_endpoint_type(ep_type_reg); + }), + Direction::In => T::dpram().ep_in_control(index - 1).write(|w| { + w.set_enable(false); + w.set_buffer_address(addr); + w.set_interrupt_per_buff(true); + w.set_endpoint_type(ep_type_reg); + }), } Ok(Endpoint { @@ -315,22 +311,21 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { let regs = T::regs(); - unsafe { - regs.inte().write(|w| { - w.set_bus_reset(true); - w.set_buff_status(true); - w.set_dev_resume_from_host(true); - w.set_dev_suspend(true); - w.set_setup_req(true); - }); - regs.int_ep_ctrl().write(|w| { - w.set_int_ep_active(0xFFFE); // all EPs - }); - regs.sie_ctrl().write(|w| { - w.set_ep0_int_1buf(true); - w.set_pullup_en(true); - }) - } + regs.inte().write(|w| { + w.set_bus_reset(true); + w.set_buff_status(true); + w.set_dev_resume_from_host(true); + w.set_dev_suspend(true); + w.set_setup_req(true); + }); + regs.int_ep_ctrl().write(|w| { + w.set_int_ep_active(0xFFFE); // all EPs + }); + regs.sie_ctrl().write(|w| { + w.set_ep0_int_1buf(true); + w.set_pullup_en(true); + }); + trace!("enabled"); ( @@ -355,7 +350,7 @@ pub struct Bus<'d, T: Instance> { impl<'d, T: Instance> driver::Bus for Bus<'d, T> { async fn poll(&mut self) -> Event { - poll_fn(move |cx| unsafe { + poll_fn(move |cx| { BUS_WAKER.register(cx.waker()); if !self.inited { @@ -425,14 +420,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { let n = ep_addr.index(); match ep_addr.direction() { - Direction::In => unsafe { + Direction::In => { T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { w.set_pid(0, true); // first packet is DATA0, but PID is flipped before }); EP_IN_WAKERS[n].wake(); - }, - Direction::Out => unsafe { + } + Direction::Out => { T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { @@ -446,7 +441,7 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { w.set_available(0, true); }); EP_OUT_WAKERS[n].wake(); - }, + } } } @@ -504,7 +499,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> { let index = self.info.addr.index(); poll_fn(|cx| { EP_IN_WAKERS[index].register(cx.waker()); - let val = unsafe { T::dpram().ep_in_control(self.info.addr.index() - 1).read() }; + let val = T::dpram().ep_in_control(self.info.addr.index() - 1).read(); if val.enable() { Poll::Ready(()) } else { @@ -526,7 +521,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, Out> { let index = self.info.addr.index(); poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); - let val = unsafe { T::dpram().ep_out_control(self.info.addr.index() - 1).read() }; + let val = T::dpram().ep_out_control(self.info.addr.index() - 1).read(); if val.enable() { Poll::Ready(()) } else { @@ -542,7 +537,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { async fn read(&mut self, buf: &mut [u8]) -> Result { trace!("READ WAITING, buf.len() = {}", buf.len()); let index = self.info.addr.index(); - let val = poll_fn(|cx| unsafe { + let val = poll_fn(|cx| { EP_OUT_WAKERS[index].register(cx.waker()); let val = T::dpram().ep_out_buffer_control(index).read(); if val.available(0) { @@ -561,19 +556,17 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> { trace!("READ OK, rx_len = {}", rx_len); - unsafe { - let pid = !val.pid(0); - T::dpram().ep_out_buffer_control(index).write(|w| { - w.set_pid(0, pid); - w.set_length(0, self.info.max_packet_size); - }); - cortex_m::asm::delay(12); - T::dpram().ep_out_buffer_control(index).write(|w| { - w.set_pid(0, pid); - w.set_length(0, self.info.max_packet_size); - w.set_available(0, true); - }); - } + let pid = !val.pid(0); + T::dpram().ep_out_buffer_control(index).write(|w| { + w.set_pid(0, pid); + w.set_length(0, self.info.max_packet_size); + }); + cortex_m::asm::delay(12); + T::dpram().ep_out_buffer_control(index).write(|w| { + w.set_pid(0, pid); + w.set_length(0, self.info.max_packet_size); + w.set_available(0, true); + }); Ok(rx_len) } @@ -588,7 +581,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { trace!("WRITE WAITING"); let index = self.info.addr.index(); - let val = poll_fn(|cx| unsafe { + let val = poll_fn(|cx| { EP_IN_WAKERS[index].register(cx.waker()); let val = T::dpram().ep_in_buffer_control(index).read(); if val.available(0) { @@ -601,21 +594,19 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> { self.buf.write(buf); - unsafe { - let pid = !val.pid(0); - T::dpram().ep_in_buffer_control(index).write(|w| { - w.set_pid(0, pid); - w.set_length(0, buf.len() as _); - w.set_full(0, true); - }); - cortex_m::asm::delay(12); - T::dpram().ep_in_buffer_control(index).write(|w| { - w.set_pid(0, pid); - w.set_length(0, buf.len() as _); - w.set_full(0, true); - w.set_available(0, true); - }); - } + let pid = !val.pid(0); + T::dpram().ep_in_buffer_control(index).write(|w| { + w.set_pid(0, pid); + w.set_length(0, buf.len() as _); + w.set_full(0, true); + }); + cortex_m::asm::delay(12); + T::dpram().ep_in_buffer_control(index).write(|w| { + w.set_pid(0, pid); + w.set_length(0, buf.len() as _); + w.set_full(0, true); + w.set_available(0, true); + }); trace!("WRITE OK"); @@ -637,9 +628,9 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { loop { trace!("SETUP read waiting"); let regs = T::regs(); - unsafe { regs.inte().write_set(|w| w.set_setup_req(true)) }; + regs.inte().write_set(|w| w.set_setup_req(true)); - poll_fn(|cx| unsafe { + poll_fn(|cx| { EP_OUT_WAKERS[0].register(cx.waker()); let regs = T::regs(); if regs.sie_status().read().setup_rec() { @@ -654,13 +645,11 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { EndpointBuffer::::new(0, 8).read(&mut buf); let regs = T::regs(); - unsafe { - regs.sie_status().write(|w| w.set_setup_rec(true)); + regs.sie_status().write(|w| w.set_setup_rec(true)); - // set PID to 0, so (after toggling) first DATA is PID 1 - T::dpram().ep_in_buffer_control(0).write(|w| w.set_pid(0, false)); - T::dpram().ep_out_buffer_control(0).write(|w| w.set_pid(0, false)); - } + // set PID to 0, so (after toggling) first DATA is PID 1 + T::dpram().ep_in_buffer_control(0).write(|w| w.set_pid(0, false)); + T::dpram().ep_out_buffer_control(0).write(|w| w.set_pid(0, false)); trace!("SETUP read ok"); return buf; @@ -668,23 +657,21 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } async fn data_out(&mut self, buf: &mut [u8], first: bool, last: bool) -> Result { - unsafe { - let bufcontrol = T::dpram().ep_out_buffer_control(0); - let pid = !bufcontrol.read().pid(0); - bufcontrol.write(|w| { - w.set_length(0, self.max_packet_size); - w.set_pid(0, pid); - }); - cortex_m::asm::delay(12); - bufcontrol.write(|w| { - w.set_length(0, self.max_packet_size); - w.set_pid(0, pid); - w.set_available(0, true); - }); - } + let bufcontrol = T::dpram().ep_out_buffer_control(0); + let pid = !bufcontrol.read().pid(0); + bufcontrol.write(|w| { + w.set_length(0, self.max_packet_size); + w.set_pid(0, pid); + }); + cortex_m::asm::delay(12); + bufcontrol.write(|w| { + w.set_length(0, self.max_packet_size); + w.set_pid(0, pid); + w.set_available(0, true); + }); trace!("control: data_out len={} first={} last={}", buf.len(), first, last); - let val = poll_fn(|cx| unsafe { + let val = poll_fn(|cx| { EP_OUT_WAKERS[0].register(cx.waker()); let val = T::dpram().ep_out_buffer_control(0).read(); if val.available(0) { @@ -714,24 +701,22 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } EndpointBuffer::::new(0x100, 64).write(data); - unsafe { - let bufcontrol = T::dpram().ep_in_buffer_control(0); - let pid = !bufcontrol.read().pid(0); - bufcontrol.write(|w| { - w.set_length(0, data.len() as _); - w.set_pid(0, pid); - w.set_full(0, true); - }); - cortex_m::asm::delay(12); - bufcontrol.write(|w| { - w.set_length(0, data.len() as _); - w.set_pid(0, pid); - w.set_full(0, true); - w.set_available(0, true); - }); - } + let bufcontrol = T::dpram().ep_in_buffer_control(0); + let pid = !bufcontrol.read().pid(0); + bufcontrol.write(|w| { + w.set_length(0, data.len() as _); + w.set_pid(0, pid); + w.set_full(0, true); + }); + cortex_m::asm::delay(12); + bufcontrol.write(|w| { + w.set_length(0, data.len() as _); + w.set_pid(0, pid); + w.set_full(0, true); + w.set_available(0, true); + }); - poll_fn(|cx| unsafe { + poll_fn(|cx| { EP_IN_WAKERS[0].register(cx.waker()); let bufcontrol = T::dpram().ep_in_buffer_control(0); if bufcontrol.read().available(0) { @@ -745,19 +730,17 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { if last { // prepare status phase right away. - unsafe { - let bufcontrol = T::dpram().ep_out_buffer_control(0); - bufcontrol.write(|w| { - w.set_length(0, 0); - w.set_pid(0, true); - }); - cortex_m::asm::delay(12); - bufcontrol.write(|w| { - w.set_length(0, 0); - w.set_pid(0, true); - w.set_available(0, true); - }); - } + let bufcontrol = T::dpram().ep_out_buffer_control(0); + bufcontrol.write(|w| { + w.set_length(0, 0); + w.set_pid(0, true); + }); + cortex_m::asm::delay(12); + bufcontrol.write(|w| { + w.set_length(0, 0); + w.set_pid(0, true); + w.set_available(0, true); + }); } Ok(()) @@ -767,26 +750,24 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { trace!("control: accept"); let bufcontrol = T::dpram().ep_in_buffer_control(0); - unsafe { - bufcontrol.write(|w| { - w.set_length(0, 0); - w.set_pid(0, true); - w.set_full(0, true); - }); - cortex_m::asm::delay(12); - bufcontrol.write(|w| { - w.set_length(0, 0); - w.set_pid(0, true); - w.set_full(0, true); - w.set_available(0, true); - }); - } + bufcontrol.write(|w| { + w.set_length(0, 0); + w.set_pid(0, true); + w.set_full(0, true); + }); + cortex_m::asm::delay(12); + bufcontrol.write(|w| { + w.set_length(0, 0); + w.set_pid(0, true); + w.set_full(0, true); + w.set_available(0, true); + }); // wait for completion before returning, needed so // set_address() doesn't happen early. poll_fn(|cx| { EP_IN_WAKERS[0].register(cx.waker()); - if unsafe { bufcontrol.read().available(0) } { + if bufcontrol.read().available(0) { Poll::Pending } else { Poll::Ready(()) @@ -799,14 +780,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { trace!("control: reject"); let regs = T::regs(); - unsafe { - regs.ep_stall_arm().write_set(|w| { - w.set_ep0_in(true); - w.set_ep0_out(true); - }); - T::dpram().ep_out_buffer_control(0).write(|w| w.set_stall(true)); - T::dpram().ep_in_buffer_control(0).write(|w| w.set_stall(true)); - } + regs.ep_stall_arm().write_set(|w| { + w.set_ep0_in(true); + w.set_ep0_out(true); + }); + T::dpram().ep_out_buffer_control(0).write(|w| w.set_stall(true)); + T::dpram().ep_in_buffer_control(0).write(|w| w.set_stall(true)); } async fn accept_set_address(&mut self, addr: u8) { @@ -814,6 +793,6 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { let regs = T::regs(); trace!("setting addr: {}", addr); - unsafe { regs.addr_endp().write(|w| w.set_address(addr)) } + regs.addr_endp().write(|w| w.set_address(addr)) } } diff --git a/embassy-rp/src/watchdog.rs b/embassy-rp/src/watchdog.rs index 78a295ae..d37795cc 100644 --- a/embassy-rp/src/watchdog.rs +++ b/embassy-rp/src/watchdog.rs @@ -35,45 +35,37 @@ impl Watchdog { /// * `cycles` - Total number of tick cycles before the next tick is generated. /// It is expected to be the frequency in MHz of clk_ref. pub fn enable_tick_generation(&mut self, cycles: u8) { - unsafe { - let watchdog = pac::WATCHDOG; - watchdog.tick().write(|w| { - w.set_enable(true); - w.set_cycles(cycles.into()) - }); - } + let watchdog = pac::WATCHDOG; + watchdog.tick().write(|w| { + w.set_enable(true); + w.set_cycles(cycles.into()) + }); } /// Defines whether or not the watchdog timer should be paused when processor(s) are in debug mode /// or when JTAG is accessing bus fabric pub fn pause_on_debug(&mut self, pause: bool) { - unsafe { - let watchdog = pac::WATCHDOG; - watchdog.ctrl().write(|w| { - w.set_pause_dbg0(pause); - w.set_pause_dbg1(pause); - w.set_pause_jtag(pause); - }) - } + let watchdog = pac::WATCHDOG; + watchdog.ctrl().write(|w| { + w.set_pause_dbg0(pause); + w.set_pause_dbg1(pause); + w.set_pause_jtag(pause); + }) } fn load_counter(&self, counter: u32) { - unsafe { - let watchdog = pac::WATCHDOG; - watchdog.load().write_value(pac::watchdog::regs::Load(counter)); - } + let watchdog = pac::WATCHDOG; + watchdog.load().write_value(pac::watchdog::regs::Load(counter)); } fn enable(&self, bit: bool) { - unsafe { - let watchdog = pac::WATCHDOG; - watchdog.ctrl().write(|w| w.set_enable(bit)) - } + let watchdog = pac::WATCHDOG; + watchdog.ctrl().write(|w| w.set_enable(bit)) } // Configure which hardware will be reset by the watchdog // (everything except ROSC, XOSC) - unsafe fn configure_wdog_reset_triggers(&self) { + fn configure_wdog_reset_triggers(&self) { let psm = pac::PSM; psm.wdsel().write_value(pac::psm::regs::Wdsel( 0x0001ffff & !(0x01 << 0usize) & !(0x01 << 1usize), @@ -100,23 +92,19 @@ impl Watchdog { self.load_value = delay_us * 2; self.enable(false); - unsafe { - self.configure_wdog_reset_triggers(); - } + self.configure_wdog_reset_triggers(); self.load_counter(self.load_value); self.enable(true); } /// Trigger a system reset pub fn trigger_reset(&mut self) { - unsafe { - self.configure_wdog_reset_triggers(); - self.pause_on_debug(false); - self.enable(true); - let watchdog = pac::WATCHDOG; - watchdog.ctrl().write(|w| { - w.set_trigger(true); - }) - } + self.configure_wdog_reset_triggers(); + self.pause_on_debug(false); + self.enable(true); + let watchdog = pac::WATCHDOG; + watchdog.ctrl().write(|w| { + w.set_trigger(true); + }) } } diff --git a/tests/rp/src/bin/float.rs b/tests/rp/src/bin/float.rs index 6a982507..0e0de85f 100644 --- a/tests/rp/src/bin/float.rs +++ b/tests/rp/src/bin/float.rs @@ -18,11 +18,9 @@ async fn main(_spawner: Spawner) { const PI_F: f32 = 3.1415926535f32; const PI_D: f64 = 3.14159265358979323846f64; - unsafe { - pac::BUSCTRL - .perfsel(0) - .write(|r| r.set_perfsel(pac::busctrl::vals::Perfsel::ROM)); - } + pac::BUSCTRL + .perfsel(0) + .write(|r| r.set_perfsel(pac::busctrl::vals::Perfsel::ROM)); for i in 0..=360 { let rad_f = (i as f32) * PI_F / 180.0; @@ -46,7 +44,7 @@ async fn main(_spawner: Spawner) { Timer::after(Duration::from_millis(10)).await; } - let rom_accesses = unsafe { pac::BUSCTRL.perfctr(0).read().perfctr() }; + let rom_accesses = pac::BUSCTRL.perfctr(0).read().perfctr(); // every float operation used here uses at least 10 cycles defmt::assert!(rom_accesses >= 360 * 12 * 10);