aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/Cargo.toml2
-rw-r--r--embassy-rp/src/adc.rs120
-rw-r--r--embassy-rp/src/clocks.rs82
-rw-r--r--embassy-rp/src/critical_section_impl.rs19
-rw-r--r--embassy-rp/src/dma.rs48
-rw-r--r--embassy-rp/src/flash.rs2
-rw-r--r--embassy-rp/src/float/div.rs78
-rw-r--r--embassy-rp/src/gpio.rs170
-rw-r--r--embassy-rp/src/i2c.rs334
-rw-r--r--embassy-rp/src/lib.rs30
-rw-r--r--embassy-rp/src/multicore.rs56
-rw-r--r--embassy-rp/src/pio.rs450
-rw-r--r--embassy-rp/src/pwm.rs90
-rw-r--r--embassy-rp/src/reset.rs4
-rw-r--r--embassy-rp/src/rtc/mod.rs89
-rw-r--r--embassy-rp/src/spi.rs219
-rw-r--r--embassy-rp/src/timer.rs30
-rw-r--r--embassy-rp/src/uart/buffered.rs269
-rw-r--r--embassy-rp/src/uart/mod.rs307
-rw-r--r--embassy-rp/src/usb.rs295
-rw-r--r--embassy-rp/src/watchdog.rs60
-rw-r--r--tests/rp/src/bin/float.rs10
22 files changed, 1255 insertions, 1509 deletions
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index b68f95385..49aa6a4d5 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -76,7 +76,7 @@ embedded-storage = { version = "0.3" }
76rand_core = "0.6.4" 76rand_core = "0.6.4"
77fixed = "1.23.1" 77fixed = "1.23.1"
78 78
79rp-pac = { version = "4" } 79rp-pac = { version = "5" }
80 80
81embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 81embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
82embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.10", optional = true} 82embedded-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 f29c4dfe1..b96d5a4a8 100644
--- a/embassy-rp/src/adc.rs
+++ b/embassy-rp/src/adc.rs
@@ -50,16 +50,14 @@ impl<'d> Adc<'d> {
50 _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>, 50 _irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>,
51 _config: Config, 51 _config: Config,
52 ) -> Self { 52 ) -> Self {
53 unsafe { 53 let reset = Self::reset();
54 let reset = Self::reset(); 54 crate::reset::reset(reset);
55 crate::reset::reset(reset); 55 crate::reset::unreset_wait(reset);
56 crate::reset::unreset_wait(reset); 56 let r = Self::regs();
57 let r = Self::regs(); 57 // Enable ADC
58 // Enable ADC 58 r.cs().write(|w| w.set_en(true));
59 r.cs().write(|w| w.set_en(true)); 59 // Wait for ADC ready
60 // Wait for ADC ready 60 while !r.cs().read().ready() {}
61 while !r.cs().read().ready() {}
62 }
63 61
64 // Setup IRQ 62 // Setup IRQ
65 interrupt::ADC_IRQ_FIFO.unpend(); 63 interrupt::ADC_IRQ_FIFO.unpend();
@@ -70,80 +68,70 @@ impl<'d> Adc<'d> {
70 68
71 async fn wait_for_ready() { 69 async fn wait_for_ready() {
72 let r = Self::regs(); 70 let r = Self::regs();
73 unsafe { 71 r.inte().write(|w| w.set_fifo(true));
74 r.inte().write(|w| w.set_fifo(true)); 72 compiler_fence(Ordering::SeqCst);
75 compiler_fence(Ordering::SeqCst); 73 poll_fn(|cx| {
76 poll_fn(|cx| { 74 WAKER.register(cx.waker());
77 WAKER.register(cx.waker()); 75 if r.cs().read().ready() {
78 if r.cs().read().ready() { 76 return Poll::Ready(());
79 return Poll::Ready(()); 77 }
80 } 78 Poll::Pending
81 Poll::Pending 79 })
82 }) 80 .await;
83 .await;
84 }
85 } 81 }
86 82
87 pub async fn read<PIN: Channel<Adc<'d>, ID = u8> + Pin>(&mut self, pin: &mut PIN) -> u16 { 83 pub async fn read<PIN: Channel<Adc<'d>, ID = u8> + Pin>(&mut self, pin: &mut PIN) -> u16 {
88 let r = Self::regs(); 84 let r = Self::regs();
89 unsafe { 85 // disable pull-down and pull-up resistors
90 // disable pull-down and pull-up resistors 86 // pull-down resistors are enabled by default
91 // pull-down resistors are enabled by default 87 pin.pad_ctrl().modify(|w| {
92 pin.pad_ctrl().modify(|w| { 88 w.set_ie(true);
93 w.set_ie(true); 89 let (pu, pd) = (false, false);
94 let (pu, pd) = (false, false); 90 w.set_pue(pu);
95 w.set_pue(pu); 91 w.set_pde(pd);
96 w.set_pde(pd); 92 });
97 }); 93 r.cs().modify(|w| {
98 r.cs().modify(|w| { 94 w.set_ainsel(PIN::channel());
99 w.set_ainsel(PIN::channel()); 95 w.set_start_once(true)
100 w.set_start_once(true) 96 });
101 }); 97 Self::wait_for_ready().await;
102 Self::wait_for_ready().await; 98 r.result().read().result().into()
103 r.result().read().result().into()
104 }
105 } 99 }
106 100
107 pub async fn read_temperature(&mut self) -> u16 { 101 pub async fn read_temperature(&mut self) -> u16 {
108 let r = Self::regs(); 102 let r = Self::regs();
109 unsafe { 103 r.cs().modify(|w| w.set_ts_en(true));
110 r.cs().modify(|w| w.set_ts_en(true)); 104 if !r.cs().read().ready() {
111 if !r.cs().read().ready() {
112 Self::wait_for_ready().await;
113 }
114 r.cs().modify(|w| {
115 w.set_ainsel(4);
116 w.set_start_once(true)
117 });
118 Self::wait_for_ready().await; 105 Self::wait_for_ready().await;
119 r.result().read().result().into()
120 } 106 }
107 r.cs().modify(|w| {
108 w.set_ainsel(4);
109 w.set_start_once(true)
110 });
111 Self::wait_for_ready().await;
112 r.result().read().result().into()
121 } 113 }
122 114
123 pub fn blocking_read<PIN: Channel<Adc<'d>, ID = u8>>(&mut self, _pin: &mut PIN) -> u16 { 115 pub fn blocking_read<PIN: Channel<Adc<'d>, ID = u8>>(&mut self, _pin: &mut PIN) -> u16 {
124 let r = Self::regs(); 116 let r = Self::regs();
125 unsafe { 117 r.cs().modify(|w| {
126 r.cs().modify(|w| { 118 w.set_ainsel(PIN::channel());
127 w.set_ainsel(PIN::channel()); 119 w.set_start_once(true)
128 w.set_start_once(true) 120 });
129 }); 121 while !r.cs().read().ready() {}
130 while !r.cs().read().ready() {} 122 r.result().read().result().into()
131 r.result().read().result().into()
132 }
133 } 123 }
134 124
135 pub fn blocking_read_temperature(&mut self) -> u16 { 125 pub fn blocking_read_temperature(&mut self) -> u16 {
136 let r = Self::regs(); 126 let r = Self::regs();
137 unsafe { 127 r.cs().modify(|w| w.set_ts_en(true));
138 r.cs().modify(|w| w.set_ts_en(true)); 128 while !r.cs().read().ready() {}
139 while !r.cs().read().ready() {} 129 r.cs().modify(|w| {
140 r.cs().modify(|w| { 130 w.set_ainsel(4);
141 w.set_ainsel(4); 131 w.set_start_once(true)
142 w.set_start_once(true) 132 });
143 }); 133 while !r.cs().read().ready() {}
144 while !r.cs().read().ready() {} 134 r.result().read().result().into()
145 r.result().read().result().into()
146 }
147 } 135 }
148} 136}
149 137
diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs
index 67439fda3..4c6223107 100644
--- a/embassy-rp/src/clocks.rs
+++ b/embassy-rp/src/clocks.rs
@@ -542,7 +542,7 @@ pub(crate) unsafe fn init(config: ClockConfig) {
542 reset::unreset_wait(peris); 542 reset::unreset_wait(peris);
543} 543}
544 544
545unsafe fn configure_rosc(config: RoscConfig) -> u32 { 545fn configure_rosc(config: RoscConfig) -> u32 {
546 let p = pac::ROSC; 546 let p = pac::ROSC;
547 547
548 p.freqa().write(|w| { 548 p.freqa().write(|w| {
@@ -620,7 +620,7 @@ pub fn clk_rtc_freq() -> u16 {
620 CLOCKS.rtc.load(Ordering::Relaxed) 620 CLOCKS.rtc.load(Ordering::Relaxed)
621} 621}
622 622
623unsafe fn start_xosc(crystal_hz: u32) { 623fn start_xosc(crystal_hz: u32) {
624 pac::XOSC 624 pac::XOSC
625 .ctrl() 625 .ctrl()
626 .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); 626 .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ));
@@ -635,7 +635,7 @@ unsafe fn start_xosc(crystal_hz: u32) {
635} 635}
636 636
637#[inline(always)] 637#[inline(always)]
638unsafe fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 { 638fn configure_pll(p: pac::pll::Pll, input_freq: u32, config: PllConfig) -> u32 {
639 let ref_freq = input_freq / config.refdiv as u32; 639 let ref_freq = input_freq / config.refdiv as u32;
640 assert!(config.fbdiv >= 16 && config.fbdiv <= 320); 640 assert!(config.fbdiv >= 16 && config.fbdiv <= 320);
641 assert!(config.post_div1 >= 1 && config.post_div1 <= 7); 641 assert!(config.post_div1 >= 1 && config.post_div1 <= 7);
@@ -700,9 +700,7 @@ impl<'d, T: Pin> Gpin<'d, T> {
700 pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> { 700 pub fn new<P: GpinPin>(gpin: impl Peripheral<P = P> + 'd) -> Gpin<'d, P> {
701 into_ref!(gpin); 701 into_ref!(gpin);
702 702
703 unsafe { 703 gpin.io().ctrl().write(|w| w.set_funcsel(0x08));
704 gpin.io().ctrl().write(|w| w.set_funcsel(0x08));
705 }
706 704
707 Gpin { 705 Gpin {
708 gpin: gpin.map_into(), 706 gpin: gpin.map_into(),
@@ -717,12 +715,10 @@ impl<'d, T: Pin> Gpin<'d, T> {
717 715
718impl<'d, T: Pin> Drop for Gpin<'d, T> { 716impl<'d, T: Pin> Drop for Gpin<'d, T> {
719 fn drop(&mut self) { 717 fn drop(&mut self) {
720 unsafe { 718 self.gpin
721 self.gpin 719 .io()
722 .io() 720 .ctrl()
723 .ctrl() 721 .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0));
724 .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0));
725 }
726 } 722 }
727} 723}
728 724
@@ -768,53 +764,43 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
768 pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self { 764 pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self {
769 into_ref!(gpout); 765 into_ref!(gpout);
770 766
771 unsafe { 767 gpout.io().ctrl().write(|w| w.set_funcsel(0x08));
772 gpout.io().ctrl().write(|w| w.set_funcsel(0x08));
773 }
774 768
775 Self { gpout } 769 Self { gpout }
776 } 770 }
777 771
778 pub fn set_div(&self, int: u32, frac: u8) { 772 pub fn set_div(&self, int: u32, frac: u8) {
779 unsafe { 773 let c = pac::CLOCKS;
780 let c = pac::CLOCKS; 774 c.clk_gpout_div(self.gpout.number()).write(|w| {
781 c.clk_gpout_div(self.gpout.number()).write(|w| { 775 w.set_int(int);
782 w.set_int(int); 776 w.set_frac(frac);
783 w.set_frac(frac); 777 });
784 });
785 }
786 } 778 }
787 779
788 pub fn set_src(&self, src: GpoutSrc) { 780 pub fn set_src(&self, src: GpoutSrc) {
789 unsafe { 781 let c = pac::CLOCKS;
790 let c = pac::CLOCKS; 782 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
791 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 783 w.set_auxsrc(ClkGpoutCtrlAuxsrc(src as _));
792 w.set_auxsrc(ClkGpoutCtrlAuxsrc(src as _)); 784 });
793 });
794 }
795 } 785 }
796 786
797 pub fn enable(&self) { 787 pub fn enable(&self) {
798 unsafe { 788 let c = pac::CLOCKS;
799 let c = pac::CLOCKS; 789 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
800 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 790 w.set_enable(true);
801 w.set_enable(true); 791 });
802 });
803 }
804 } 792 }
805 793
806 pub fn disable(&self) { 794 pub fn disable(&self) {
807 unsafe { 795 let c = pac::CLOCKS;
808 let c = pac::CLOCKS; 796 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| {
809 c.clk_gpout_ctrl(self.gpout.number()).modify(|w| { 797 w.set_enable(false);
810 w.set_enable(false); 798 });
811 });
812 }
813 } 799 }
814 800
815 pub fn get_freq(&self) -> u32 { 801 pub fn get_freq(&self) -> u32 {
816 let c = pac::CLOCKS; 802 let c = pac::CLOCKS;
817 let src = unsafe { c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc() }; 803 let src = c.clk_gpout_ctrl(self.gpout.number()).read().auxsrc();
818 804
819 let base = match src { 805 let base = match src {
820 ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(), 806 ClkGpoutCtrlAuxsrc::CLKSRC_PLL_SYS => pll_sys_freq(),
@@ -831,7 +817,7 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
831 _ => unreachable!(), 817 _ => unreachable!(),
832 }; 818 };
833 819
834 let div = unsafe { c.clk_gpout_div(self.gpout.number()).read() }; 820 let div = c.clk_gpout_div(self.gpout.number()).read();
835 let int = if div.int() == 0 { 65536 } else { div.int() } as u64; 821 let int = if div.int() == 0 { 65536 } else { div.int() } as u64;
836 let frac = div.frac() as u64; 822 let frac = div.frac() as u64;
837 823
@@ -842,12 +828,10 @@ impl<'d, T: GpoutPin> Gpout<'d, T> {
842impl<'d, T: GpoutPin> Drop for Gpout<'d, T> { 828impl<'d, T: GpoutPin> Drop for Gpout<'d, T> {
843 fn drop(&mut self) { 829 fn drop(&mut self) {
844 self.disable(); 830 self.disable();
845 unsafe { 831 self.gpout
846 self.gpout 832 .io()
847 .io() 833 .ctrl()
848 .ctrl() 834 .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0));
849 .write(|w| w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0));
850 }
851 } 835 }
852} 836}
853 837
@@ -864,7 +848,7 @@ impl RoscRng {
864 let mut acc = 0; 848 let mut acc = 0;
865 for _ in 0..u8::BITS { 849 for _ in 0..u8::BITS {
866 acc <<= 1; 850 acc <<= 1;
867 acc |= unsafe { random_reg.read().randombit() as u8 }; 851 acc |= random_reg.read().randombit() as u8;
868 } 852 }
869 acc 853 acc
870 } 854 }
diff --git a/embassy-rp/src/critical_section_impl.rs b/embassy-rp/src/critical_section_impl.rs
index ce284c856..d233e6fab 100644
--- a/embassy-rp/src/critical_section_impl.rs
+++ b/embassy-rp/src/critical_section_impl.rs
@@ -103,14 +103,11 @@ where
103 /// Try to claim the spinlock. Will return `Some(Self)` if the lock is obtained, and `None` if the lock is 103 /// Try to claim the spinlock. Will return `Some(Self)` if the lock is obtained, and `None` if the lock is
104 /// already in use somewhere else. 104 /// already in use somewhere else.
105 pub fn try_claim() -> Option<Self> { 105 pub fn try_claim() -> Option<Self> {
106 // Safety: We're only reading from this register 106 let lock = pac::SIO.spinlock(N).read();
107 unsafe { 107 if lock > 0 {
108 let lock = pac::SIO.spinlock(N).read(); 108 Some(Self(core::marker::PhantomData))
109 if lock > 0 { 109 } else {
110 Some(Self(core::marker::PhantomData)) 110 None
111 } else {
112 None
113 }
114 } 111 }
115 } 112 }
116 113
@@ -120,10 +117,8 @@ where
120 /// 117 ///
121 /// Only call this function if you hold the spin-lock. 118 /// Only call this function if you hold the spin-lock.
122 pub unsafe fn release() { 119 pub unsafe fn release() {
123 unsafe { 120 // Write (any value): release the lock
124 // Write (any value): release the lock 121 pac::SIO.spinlock(N).write_value(1);
125 pac::SIO.spinlock(N).write_value(1);
126 }
127 } 122 }
128} 123}
129 124
diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs
index 25819f03e..1a458778c 100644
--- a/embassy-rp/src/dma.rs
+++ b/embassy-rp/src/dma.rs
@@ -14,7 +14,7 @@ use crate::{interrupt, pac, peripherals};
14 14
15#[cfg(feature = "rt")] 15#[cfg(feature = "rt")]
16#[interrupt] 16#[interrupt]
17unsafe fn DMA_IRQ_0() { 17fn DMA_IRQ_0() {
18 let ints0 = pac::DMA.ints0().read().ints0(); 18 let ints0 = pac::DMA.ints0().read().ints0();
19 for channel in 0..CHANNEL_COUNT { 19 for channel in 0..CHANNEL_COUNT {
20 let ctrl_trig = pac::DMA.ch(channel).ctrl_trig().read(); 20 let ctrl_trig = pac::DMA.ch(channel).ctrl_trig().read();
@@ -128,28 +128,26 @@ fn copy_inner<'a, C: Channel>(
128) -> Transfer<'a, C> { 128) -> Transfer<'a, C> {
129 into_ref!(ch); 129 into_ref!(ch);
130 130
131 unsafe { 131 let p = ch.regs();
132 let p = ch.regs();
133 132
134 p.read_addr().write_value(from as u32); 133 p.read_addr().write_value(from as u32);
135 p.write_addr().write_value(to as u32); 134 p.write_addr().write_value(to as u32);
136 p.trans_count().write_value(len as u32); 135 p.trans_count().write_value(len as u32);
137 136
138 compiler_fence(Ordering::SeqCst); 137 compiler_fence(Ordering::SeqCst);
139 138
140 p.ctrl_trig().write(|w| { 139 p.ctrl_trig().write(|w| {
141 // TODO: Add all DREQ options to pac vals::TreqSel, and use 140 // TODO: Add all DREQ options to pac vals::TreqSel, and use
142 // `set_treq:sel` 141 // `set_treq:sel`
143 w.0 = ((dreq as u32) & 0x3f) << 15usize; 142 w.0 = ((dreq as u32) & 0x3f) << 15usize;
144 w.set_data_size(data_size); 143 w.set_data_size(data_size);
145 w.set_incr_read(incr_read); 144 w.set_incr_read(incr_read);
146 w.set_incr_write(incr_write); 145 w.set_incr_write(incr_write);
147 w.set_chain_to(ch.number()); 146 w.set_chain_to(ch.number());
148 w.set_en(true); 147 w.set_en(true);
149 }); 148 });
150 149
151 compiler_fence(Ordering::SeqCst); 150 compiler_fence(Ordering::SeqCst);
152 }
153 Transfer::new(ch) 151 Transfer::new(ch)
154} 152}
155 153
@@ -169,12 +167,10 @@ impl<'a, C: Channel> Transfer<'a, C> {
169impl<'a, C: Channel> Drop for Transfer<'a, C> { 167impl<'a, C: Channel> Drop for Transfer<'a, C> {
170 fn drop(&mut self) { 168 fn drop(&mut self) {
171 let p = self.channel.regs(); 169 let p = self.channel.regs();
172 unsafe { 170 pac::DMA
173 pac::DMA 171 .chan_abort()
174 .chan_abort() 172 .modify(|m| m.set_chan_abort(1 << self.channel.number()));
175 .modify(|m| m.set_chan_abort(1 << self.channel.number())); 173 while p.ctrl_trig().read().busy() {}
176 while p.ctrl_trig().read().busy() {}
177 }
178 } 174 }
179} 175}
180 176
@@ -186,7 +182,7 @@ impl<'a, C: Channel> Future for Transfer<'a, C> {
186 // calls to wake will deregister the waker. 182 // calls to wake will deregister the waker.
187 CHANNEL_WAKERS[self.channel.number() as usize].register(cx.waker()); 183 CHANNEL_WAKERS[self.channel.number() as usize].register(cx.waker());
188 184
189 if unsafe { self.channel.regs().ctrl_trig().read().busy() } { 185 if self.channel.regs().ctrl_trig().read().busy() {
190 Poll::Pending 186 Poll::Pending
191 } else { 187 } else {
192 Poll::Ready(()) 188 Poll::Ready(())
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
index 5d928abad..96d2d4541 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> {
167 /// - DMA must not access flash memory 167 /// - DMA must not access flash memory
168 unsafe fn in_ram(&mut self, operation: impl FnOnce()) -> Result<(), Error> { 168 unsafe fn in_ram(&mut self, operation: impl FnOnce()) -> Result<(), Error> {
169 // Make sure we're running on CORE0 169 // Make sure we're running on CORE0
170 let core_id: u32 = unsafe { pac::SIO.cpuid().read() }; 170 let core_id: u32 = pac::SIO.cpuid().read();
171 if core_id != 0 { 171 if core_id != 0 {
172 return Err(Error::InvalidCore); 172 return Err(Error::InvalidCore);
173 } 173 }
diff --git a/embassy-rp/src/float/div.rs b/embassy-rp/src/float/div.rs
index 094dec446..aff0dcb07 100644
--- a/embassy-rp/src/float/div.rs
+++ b/embassy-rp/src/float/div.rs
@@ -17,45 +17,43 @@ where
17{ 17{
18 let sio = rp_pac::SIO; 18 let sio = rp_pac::SIO;
19 19
20 unsafe { 20 // Since we can't save the signed-ness of the calculation, we have to make
21 // Since we can't save the signed-ness of the calculation, we have to make 21 // sure that there's at least an 8 cycle delay before we read the result.
22 // sure that there's at least an 8 cycle delay before we read the result. 22 // The Pico SDK ensures this by using a 6 cycle push and two 1 cycle reads.
23 // The Pico SDK ensures this by using a 6 cycle push and two 1 cycle reads. 23 // Since we can't be sure the Rust implementation will optimize to the same,
24 // Since we can't be sure the Rust implementation will optimize to the same, 24 // just use an explicit wait.
25 // just use an explicit wait. 25 while !sio.div().csr().read().ready() {}
26 while !sio.div().csr().read().ready() {} 26
27 27 // Read the quotient last, since that's what clears the dirty flag
28 // Read the quotient last, since that's what clears the dirty flag 28 let dividend = sio.div().udividend().read();
29 let dividend = sio.div().udividend().read(); 29 let divisor = sio.div().udivisor().read();
30 let divisor = sio.div().udivisor().read(); 30 let remainder = sio.div().remainder().read();
31 let remainder = sio.div().remainder().read(); 31 let quotient = sio.div().quotient().read();
32 let quotient = sio.div().quotient().read(); 32
33 33 // If we get interrupted here (before a write sets the DIRTY flag) its fine, since
34 // If we get interrupted here (before a write sets the DIRTY flag) its fine, since 34 // we have the full state, so the interruptor doesn't have to restore it. Once the
35 // we have the full state, so the interruptor doesn't have to restore it. Once the 35 // write happens and the DIRTY flag is set, the interruptor becomes responsible for
36 // write happens and the DIRTY flag is set, the interruptor becomes responsible for 36 // restoring our state.
37 // restoring our state. 37 let result = f();
38 let result = f(); 38
39 39 // If we are interrupted here, then the interruptor will start an incorrect calculation
40 // If we are interrupted here, then the interruptor will start an incorrect calculation 40 // using a wrong divisor, but we'll restore the divisor and result ourselves correctly.
41 // using a wrong divisor, but we'll restore the divisor and result ourselves correctly. 41 // This sets DIRTY, so any interruptor will save the state.
42 // This sets DIRTY, so any interruptor will save the state. 42 sio.div().udividend().write_value(dividend);
43 sio.div().udividend().write_value(dividend); 43 // If we are interrupted here, the the interruptor may start the calculation using
44 // If we are interrupted here, the the interruptor may start the calculation using 44 // incorrectly signed inputs, but we'll restore the result ourselves.
45 // incorrectly signed inputs, but we'll restore the result ourselves. 45 // This sets DIRTY, so any interruptor will save the state.
46 // This sets DIRTY, so any interruptor will save the state. 46 sio.div().udivisor().write_value(divisor);
47 sio.div().udivisor().write_value(divisor); 47 // If we are interrupted here, the interruptor will have restored everything but the
48 // If we are interrupted here, the interruptor will have restored everything but the 48 // quotient may be wrongly signed. If the calculation started by the above writes is
49 // quotient may be wrongly signed. If the calculation started by the above writes is 49 // still ongoing it is stopped, so it won't replace the result we're restoring.
50 // still ongoing it is stopped, so it won't replace the result we're restoring. 50 // DIRTY and READY set, but only DIRTY matters to make the interruptor save the state.
51 // DIRTY and READY set, but only DIRTY matters to make the interruptor save the state. 51 sio.div().remainder().write_value(remainder);
52 sio.div().remainder().write_value(remainder); 52 // State fully restored after the quotient write. This sets both DIRTY and READY, so
53 // State fully restored after the quotient write. This sets both DIRTY and READY, so 53 // whatever we may have interrupted can read the result.
54 // whatever we may have interrupted can read the result. 54 sio.div().quotient().write_value(quotient);
55 sio.div().quotient().write_value(quotient); 55
56 56 result
57 result
58 }
59} 57}
60 58
61fn save_divider<F, R>(f: F) -> R 59fn save_divider<F, R>(f: F) -> R
@@ -63,7 +61,7 @@ where
63 F: FnOnce() -> R, 61 F: FnOnce() -> R,
64{ 62{
65 let sio = rp_pac::SIO; 63 let sio = rp_pac::SIO;
66 if unsafe { !sio.div().csr().read().dirty() } { 64 if !sio.div().csr().read().dirty() {
67 // Not dirty, so nothing is waiting for the calculation. So we can just 65 // Not dirty, so nothing is waiting for the calculation. So we can just
68 // issue it directly without a save/restore. 66 // issue it directly without a save/restore.
69 f() 67 f()
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index 66faa2489..ce0d02557 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -144,7 +144,7 @@ pub(crate) unsafe fn init() {
144 144
145#[cfg(feature = "rt")] 145#[cfg(feature = "rt")]
146#[interrupt] 146#[interrupt]
147unsafe fn IO_IRQ_BANK0() { 147fn IO_IRQ_BANK0() {
148 let cpu = SIO.cpuid().read() as usize; 148 let cpu = SIO.cpuid().read() as usize;
149 // There are two sets of interrupt registers, one for cpu0 and one for cpu1 149 // There are two sets of interrupt registers, one for cpu0 and one for cpu1
150 // and here we are selecting the set that belongs to the currently executing 150 // and here we are selecting the set that belongs to the currently executing
@@ -185,47 +185,45 @@ struct InputFuture<'a, T: Pin> {
185impl<'d, T: Pin> InputFuture<'d, T> { 185impl<'d, T: Pin> InputFuture<'d, T> {
186 pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self { 186 pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self {
187 into_ref!(pin); 187 into_ref!(pin);
188 unsafe { 188 let pin_group = (pin.pin() % 8) as usize;
189 let pin_group = (pin.pin() % 8) as usize; 189 // first, clear the INTR register bits. without this INTR will still
190 // first, clear the INTR register bits. without this INTR will still 190 // contain reports of previous edges, causing the IRQ to fire early
191 // contain reports of previous edges, causing the IRQ to fire early 191 // on stale state. clearing these means that we can only detect edges
192 // on stale state. clearing these means that we can only detect edges 192 // that occur *after* the clear happened, but since both this and the
193 // that occur *after* the clear happened, but since both this and the 193 // alternative are fundamentally racy it's probably fine.
194 // alternative are fundamentally racy it's probably fine. 194 // (the alternative being checking the current level and waiting for
195 // (the alternative being checking the current level and waiting for 195 // its inverse, but that requires reading the current level and thus
196 // its inverse, but that requires reading the current level and thus 196 // missing anything that happened before the level was read.)
197 // missing anything that happened before the level was read.) 197 pac::IO_BANK0.intr(pin.pin() as usize / 8).write(|w| {
198 pac::IO_BANK0.intr(pin.pin() as usize / 8).write(|w| { 198 w.set_edge_high(pin_group, true);
199 w.set_edge_high(pin_group, true); 199 w.set_edge_low(pin_group, true);
200 w.set_edge_low(pin_group, true); 200 });
201
202 // Each INTR register is divided into 8 groups, one group for each
203 // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW,
204 // and EGDE_HIGH.
205 pin.int_proc()
206 .inte((pin.pin() / 8) as usize)
207 .write_set(|w| match level {
208 InterruptTrigger::LevelHigh => {
209 trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin());
210 w.set_level_high(pin_group, true);
211 }
212 InterruptTrigger::LevelLow => {
213 w.set_level_low(pin_group, true);
214 }
215 InterruptTrigger::EdgeHigh => {
216 w.set_edge_high(pin_group, true);
217 }
218 InterruptTrigger::EdgeLow => {
219 w.set_edge_low(pin_group, true);
220 }
221 InterruptTrigger::AnyEdge => {
222 w.set_edge_high(pin_group, true);
223 w.set_edge_low(pin_group, true);
224 }
201 }); 225 });
202 226
203 // Each INTR register is divided into 8 groups, one group for each
204 // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW,
205 // and EGDE_HIGH.
206 pin.int_proc()
207 .inte((pin.pin() / 8) as usize)
208 .write_set(|w| match level {
209 InterruptTrigger::LevelHigh => {
210 trace!("InputFuture::new enable LevelHigh for pin {}", pin.pin());
211 w.set_level_high(pin_group, true);
212 }
213 InterruptTrigger::LevelLow => {
214 w.set_level_low(pin_group, true);
215 }
216 InterruptTrigger::EdgeHigh => {
217 w.set_edge_high(pin_group, true);
218 }
219 InterruptTrigger::EdgeLow => {
220 w.set_edge_low(pin_group, true);
221 }
222 InterruptTrigger::AnyEdge => {
223 w.set_edge_high(pin_group, true);
224 w.set_edge_low(pin_group, true);
225 }
226 });
227 }
228
229 Self { pin, level } 227 Self { pin, level }
230 } 228 }
231} 229}
@@ -242,7 +240,7 @@ impl<'d, T: Pin> Future for InputFuture<'d, T> {
242 // then we want to access the interrupt enable register for our 240 // then we want to access the interrupt enable register for our
243 // pin (there are 4 of these PROC0_INTE0, PROC0_INTE1, PROC0_INTE2, and 241 // pin (there are 4 of these PROC0_INTE0, PROC0_INTE1, PROC0_INTE2, and
244 // PROC0_INTE3 per cpu). 242 // PROC0_INTE3 per cpu).
245 let inte: pac::io::regs::Int = unsafe { self.pin.int_proc().inte((self.pin.pin() / 8) as usize).read() }; 243 let inte: pac::io::regs::Int = self.pin.int_proc().inte((self.pin.pin() / 8) as usize).read();
246 // The register is divided into groups of four, one group for 244 // The register is divided into groups of four, one group for
247 // each pin. Each group consists of four trigger levels LEVEL_LOW, 245 // each pin. Each group consists of four trigger levels LEVEL_LOW,
248 // LEVEL_HIGH, EDGE_LOW, and EDGE_HIGH for each pin. 246 // LEVEL_HIGH, EDGE_LOW, and EDGE_HIGH for each pin.
@@ -449,15 +447,13 @@ impl<'d, T: Pin> Flex<'d, T> {
449 pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self { 447 pub fn new(pin: impl Peripheral<P = T> + 'd) -> Self {
450 into_ref!(pin); 448 into_ref!(pin);
451 449
452 unsafe { 450 pin.pad_ctrl().write(|w| {
453 pin.pad_ctrl().write(|w| { 451 w.set_ie(true);
454 w.set_ie(true); 452 });
455 });
456 453
457 pin.io().ctrl().write(|w| { 454 pin.io().ctrl().write(|w| {
458 w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::SIO_0.0); 455 w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::SIO_0.0);
459 }); 456 });
460 }
461 457
462 Self { pin } 458 Self { pin }
463 } 459 }
@@ -470,43 +466,37 @@ impl<'d, T: Pin> Flex<'d, T> {
470 /// Set the pin's pull. 466 /// Set the pin's pull.
471 #[inline] 467 #[inline]
472 pub fn set_pull(&mut self, pull: Pull) { 468 pub fn set_pull(&mut self, pull: Pull) {
473 unsafe { 469 self.pin.pad_ctrl().modify(|w| {
474 self.pin.pad_ctrl().modify(|w| { 470 w.set_ie(true);
475 w.set_ie(true); 471 let (pu, pd) = match pull {
476 let (pu, pd) = match pull { 472 Pull::Up => (true, false),
477 Pull::Up => (true, false), 473 Pull::Down => (false, true),
478 Pull::Down => (false, true), 474 Pull::None => (false, false),
479 Pull::None => (false, false), 475 };
480 }; 476 w.set_pue(pu);
481 w.set_pue(pu); 477 w.set_pde(pd);
482 w.set_pde(pd); 478 });
483 });
484 }
485 } 479 }
486 480
487 /// Set the pin's drive strength. 481 /// Set the pin's drive strength.
488 #[inline] 482 #[inline]
489 pub fn set_drive_strength(&mut self, strength: Drive) { 483 pub fn set_drive_strength(&mut self, strength: Drive) {
490 unsafe { 484 self.pin.pad_ctrl().modify(|w| {
491 self.pin.pad_ctrl().modify(|w| { 485 w.set_drive(match strength {
492 w.set_drive(match strength { 486 Drive::_2mA => pac::pads::vals::Drive::_2MA,
493 Drive::_2mA => pac::pads::vals::Drive::_2MA, 487 Drive::_4mA => pac::pads::vals::Drive::_4MA,
494 Drive::_4mA => pac::pads::vals::Drive::_4MA, 488 Drive::_8mA => pac::pads::vals::Drive::_8MA,
495 Drive::_8mA => pac::pads::vals::Drive::_8MA, 489 Drive::_12mA => pac::pads::vals::Drive::_12MA,
496 Drive::_12mA => pac::pads::vals::Drive::_12MA,
497 });
498 }); 490 });
499 } 491 });
500 } 492 }
501 493
502 // Set the pin's slew rate. 494 // Set the pin's slew rate.
503 #[inline] 495 #[inline]
504 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 496 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
505 unsafe { 497 self.pin.pad_ctrl().modify(|w| {
506 self.pin.pad_ctrl().modify(|w| { 498 w.set_slewfast(slew_rate == SlewRate::Fast);
507 w.set_slewfast(slew_rate == SlewRate::Fast); 499 });
508 });
509 }
510 } 500 }
511 501
512 /// Put the pin into input mode. 502 /// Put the pin into input mode.
@@ -514,7 +504,7 @@ impl<'d, T: Pin> Flex<'d, T> {
514 /// The pull setting is left unchanged. 504 /// The pull setting is left unchanged.
515 #[inline] 505 #[inline]
516 pub fn set_as_input(&mut self) { 506 pub fn set_as_input(&mut self) {
517 unsafe { self.pin.sio_oe().value_clr().write_value(self.bit()) } 507 self.pin.sio_oe().value_clr().write_value(self.bit())
518 } 508 }
519 509
520 /// Put the pin into output mode. 510 /// Put the pin into output mode.
@@ -523,17 +513,17 @@ impl<'d, T: Pin> Flex<'d, T> {
523 /// at a specific level, call `set_high`/`set_low` on the pin first. 513 /// at a specific level, call `set_high`/`set_low` on the pin first.
524 #[inline] 514 #[inline]
525 pub fn set_as_output(&mut self) { 515 pub fn set_as_output(&mut self) {
526 unsafe { self.pin.sio_oe().value_set().write_value(self.bit()) } 516 self.pin.sio_oe().value_set().write_value(self.bit())
527 } 517 }
528 518
529 #[inline] 519 #[inline]
530 fn is_set_as_output(&self) -> bool { 520 fn is_set_as_output(&self) -> bool {
531 unsafe { (self.pin.sio_oe().value().read() & self.bit()) != 0 } 521 (self.pin.sio_oe().value().read() & self.bit()) != 0
532 } 522 }
533 523
534 #[inline] 524 #[inline]
535 pub fn toggle_set_as_output(&mut self) { 525 pub fn toggle_set_as_output(&mut self) {
536 unsafe { self.pin.sio_oe().value_xor().write_value(self.bit()) } 526 self.pin.sio_oe().value_xor().write_value(self.bit())
537 } 527 }
538 528
539 #[inline] 529 #[inline]
@@ -543,7 +533,7 @@ impl<'d, T: Pin> Flex<'d, T> {
543 533
544 #[inline] 534 #[inline]
545 pub fn is_low(&self) -> bool { 535 pub fn is_low(&self) -> bool {
546 unsafe { self.pin.sio_in().read() & self.bit() == 0 } 536 self.pin.sio_in().read() & self.bit() == 0
547 } 537 }
548 538
549 /// Returns current pin level 539 /// Returns current pin level
@@ -555,13 +545,13 @@ impl<'d, T: Pin> Flex<'d, T> {
555 /// Set the output as high. 545 /// Set the output as high.
556 #[inline] 546 #[inline]
557 pub fn set_high(&mut self) { 547 pub fn set_high(&mut self) {
558 unsafe { self.pin.sio_out().value_set().write_value(self.bit()) } 548 self.pin.sio_out().value_set().write_value(self.bit())
559 } 549 }
560 550
561 /// Set the output as low. 551 /// Set the output as low.
562 #[inline] 552 #[inline]
563 pub fn set_low(&mut self) { 553 pub fn set_low(&mut self) {
564 unsafe { self.pin.sio_out().value_clr().write_value(self.bit()) } 554 self.pin.sio_out().value_clr().write_value(self.bit())
565 } 555 }
566 556
567 /// Set the output level. 557 /// Set the output level.
@@ -576,7 +566,7 @@ impl<'d, T: Pin> Flex<'d, T> {
576 /// Is the output level high? 566 /// Is the output level high?
577 #[inline] 567 #[inline]
578 pub fn is_set_high(&self) -> bool { 568 pub fn is_set_high(&self) -> bool {
579 unsafe { (self.pin.sio_out().value().read() & self.bit()) == 0 } 569 (self.pin.sio_out().value().read() & self.bit()) == 0
580 } 570 }
581 571
582 /// Is the output level low? 572 /// Is the output level low?
@@ -594,7 +584,7 @@ impl<'d, T: Pin> Flex<'d, T> {
594 /// Toggle pin output 584 /// Toggle pin output
595 #[inline] 585 #[inline]
596 pub fn toggle(&mut self) { 586 pub fn toggle(&mut self) {
597 unsafe { self.pin.sio_out().value_xor().write_value(self.bit()) } 587 self.pin.sio_out().value_xor().write_value(self.bit())
598 } 588 }
599 589
600 #[inline] 590 #[inline]
@@ -626,12 +616,10 @@ impl<'d, T: Pin> Flex<'d, T> {
626impl<'d, T: Pin> Drop for Flex<'d, T> { 616impl<'d, T: Pin> Drop for Flex<'d, T> {
627 #[inline] 617 #[inline]
628 fn drop(&mut self) { 618 fn drop(&mut self) {
629 unsafe { 619 self.pin.pad_ctrl().write(|_| {});
630 self.pin.pad_ctrl().write(|_| {}); 620 self.pin.io().ctrl().write(|w| {
631 self.pin.io().ctrl().write(|w| { 621 w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0);
632 w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::NULL.0); 622 });
633 });
634 }
635 } 623 }
636} 624}
637 625
@@ -688,7 +676,7 @@ pub(crate) mod sealed {
688 Bank::Bank0 => crate::pac::IO_BANK0, 676 Bank::Bank0 => crate::pac::IO_BANK0,
689 Bank::Qspi => crate::pac::IO_QSPI, 677 Bank::Qspi => crate::pac::IO_QSPI,
690 }; 678 };
691 let proc = unsafe { SIO.cpuid().read() }; 679 let proc = SIO.cpuid().read();
692 io_block.int_proc(proc as _) 680 io_block.int_proc(proc as _)
693 } 681 }
694 } 682 }
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index ce9a082a2..791c64554 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> {
85 let r = T::regs(); 85 let r = T::regs();
86 86
87 // mask everything initially 87 // mask everything initially
88 unsafe { r.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)) } 88 r.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0));
89 T::Interrupt::unpend(); 89 T::Interrupt::unpend();
90 unsafe { T::Interrupt::enable() }; 90 unsafe { T::Interrupt::enable() };
91 91
@@ -135,13 +135,11 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
135 let last = remaining_queue == 0; 135 let last = remaining_queue == 0;
136 batch += 1; 136 batch += 1;
137 137
138 unsafe { 138 p.ic_data_cmd().write(|w| {
139 p.ic_data_cmd().write(|w| { 139 w.set_restart(restart && remaining_queue == buffer.len() - 1);
140 w.set_restart(restart && remaining_queue == buffer.len() - 1); 140 w.set_stop(last && send_stop);
141 w.set_stop(last && send_stop); 141 w.set_cmd(true);
142 w.set_cmd(true); 142 });
143 });
144 }
145 } 143 }
146 144
147 // We've either run out of txfifo or just plain finished setting up 145 // 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> {
161 Poll::Pending 159 Poll::Pending
162 } 160 }
163 }, 161 },
164 |_me| unsafe { 162 |_me| {
165 // Set the read threshold to the number of bytes we're 163 // Set the read threshold to the number of bytes we're
166 // expecting so we don't get spurious interrupts. 164 // expecting so we don't get spurious interrupts.
167 p.ic_rx_tl().write(|w| w.set_rx_tl(batch - 1)); 165 p.ic_rx_tl().write(|w| w.set_rx_tl(batch - 1));
@@ -185,7 +183,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
185 let rxbytes = (rxfifo as usize).min(remaining); 183 let rxbytes = (rxfifo as usize).min(remaining);
186 let received = buffer.len() - remaining; 184 let received = buffer.len() - remaining;
187 for b in &mut buffer[received..received + rxbytes] { 185 for b in &mut buffer[received..received + rxbytes] {
188 *b = unsafe { p.ic_data_cmd().read().dat() }; 186 *b = p.ic_data_cmd().read().dat();
189 } 187 }
190 remaining -= rxbytes; 188 remaining -= rxbytes;
191 } 189 }
@@ -211,13 +209,11 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
211 if let Some(byte) = bytes.next() { 209 if let Some(byte) = bytes.next() {
212 let last = bytes.peek().is_none(); 210 let last = bytes.peek().is_none();
213 211
214 unsafe { 212 p.ic_data_cmd().write(|w| {
215 p.ic_data_cmd().write(|w| { 213 w.set_stop(last && send_stop);
216 w.set_stop(last && send_stop); 214 w.set_cmd(false);
217 w.set_cmd(false); 215 w.set_dat(byte);
218 w.set_dat(byte); 216 });
219 });
220 }
221 } else { 217 } else {
222 break 'xmit Ok(()); 218 break 'xmit Ok(());
223 } 219 }
@@ -235,7 +231,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
235 Poll::Pending 231 Poll::Pending
236 } 232 }
237 }, 233 },
238 |_me| unsafe { 234 |_me| {
239 // Set tx "free" threshold a little high so that we get 235 // Set tx "free" threshold a little high so that we get
240 // woken before the fifo completely drains to minimize 236 // woken before the fifo completely drains to minimize
241 // transfer stalls. 237 // transfer stalls.
@@ -267,7 +263,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
267 263
268 let had_abort2 = self 264 let had_abort2 = self
269 .wait_on( 265 .wait_on(
270 |me| unsafe { 266 |me| {
271 // We could see an abort while processing fifo backlog, 267 // We could see an abort while processing fifo backlog,
272 // so handle it here. 268 // so handle it here.
273 let abort = me.read_and_clear_abort_reason(); 269 let abort = me.read_and_clear_abort_reason();
@@ -279,7 +275,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
279 Poll::Pending 275 Poll::Pending
280 } 276 }
281 }, 277 },
282 |_me| unsafe { 278 |_me| {
283 p.ic_intr_mask().modify(|w| { 279 p.ic_intr_mask().modify(|w| {
284 w.set_m_stop_det(true); 280 w.set_m_stop_det(true);
285 w.set_m_tx_abrt(true); 281 w.set_m_tx_abrt(true);
@@ -287,9 +283,7 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
287 }, 283 },
288 ) 284 )
289 .await; 285 .await;
290 unsafe { 286 p.ic_clr_stop_det().read();
291 p.ic_clr_stop_det().read();
292 }
293 287
294 had_abort.and(had_abort2) 288 had_abort.and(had_abort2)
295 } else { 289 } else {
@@ -336,95 +330,93 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
336 330
337 let p = T::regs(); 331 let p = T::regs();
338 332
339 unsafe { 333 let reset = T::reset();
340 let reset = T::reset(); 334 crate::reset::reset(reset);
341 crate::reset::reset(reset); 335 crate::reset::unreset_wait(reset);
342 crate::reset::unreset_wait(reset); 336
343 337 p.ic_enable().write(|w| w.set_enable(false));
344 p.ic_enable().write(|w| w.set_enable(false)); 338
345 339 // Select controller mode & speed
346 // Select controller mode & speed 340 p.ic_con().modify(|w| {
347 p.ic_con().modify(|w| { 341 // Always use "fast" mode (<= 400 kHz, works fine for standard
348 // Always use "fast" mode (<= 400 kHz, works fine for standard 342 // mode too)
349 // mode too) 343 w.set_speed(i2c::vals::Speed::FAST);
350 w.set_speed(i2c::vals::Speed::FAST); 344 w.set_master_mode(true);
351 w.set_master_mode(true); 345 w.set_ic_slave_disable(true);
352 w.set_ic_slave_disable(true); 346 w.set_ic_restart_en(true);
353 w.set_ic_restart_en(true); 347 w.set_tx_empty_ctrl(true);
354 w.set_tx_empty_ctrl(true); 348 });
355 }); 349
356 350 // Set FIFO watermarks to 1 to make things simpler. This is encoded
357 // Set FIFO watermarks to 1 to make things simpler. This is encoded 351 // by a register value of 0.
358 // by a register value of 0. 352 p.ic_tx_tl().write(|w| w.set_tx_tl(0));
359 p.ic_tx_tl().write(|w| w.set_tx_tl(0)); 353 p.ic_rx_tl().write(|w| w.set_rx_tl(0));
360 p.ic_rx_tl().write(|w| w.set_rx_tl(0)); 354
361 355 // Configure SCL & SDA pins
362 // Configure SCL & SDA pins 356 scl.io().ctrl().write(|w| w.set_funcsel(3));
363 scl.io().ctrl().write(|w| w.set_funcsel(3)); 357 sda.io().ctrl().write(|w| w.set_funcsel(3));
364 sda.io().ctrl().write(|w| w.set_funcsel(3)); 358
365 359 scl.pad_ctrl().write(|w| {
366 scl.pad_ctrl().write(|w| { 360 w.set_schmitt(true);
367 w.set_schmitt(true); 361 w.set_ie(true);
368 w.set_ie(true); 362 w.set_od(false);
369 w.set_od(false); 363 w.set_pue(true);
370 w.set_pue(true); 364 w.set_pde(false);
371 w.set_pde(false); 365 });
372 }); 366 sda.pad_ctrl().write(|w| {
373 sda.pad_ctrl().write(|w| { 367 w.set_schmitt(true);
374 w.set_schmitt(true); 368 w.set_ie(true);
375 w.set_ie(true); 369 w.set_od(false);
376 w.set_od(false); 370 w.set_pue(true);
377 w.set_pue(true); 371 w.set_pde(false);
378 w.set_pde(false); 372 });
379 }); 373
374 // Configure baudrate
375
376 // There are some subtleties to I2C timing which we are completely
377 // ignoring here See:
378 // https://github.com/raspberrypi/pico-sdk/blob/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7/src/rp2_common/hardware_i2c/i2c.c#L69
379 let clk_base = crate::clocks::clk_peri_freq();
380
381 let period = (clk_base + config.frequency / 2) / config.frequency;
382 let lcnt = period * 3 / 5; // spend 3/5 (60%) of the period low
383 let hcnt = period - lcnt; // and 2/5 (40%) of the period high
384
385 // Check for out-of-range divisors:
386 assert!(hcnt <= 0xffff);
387 assert!(lcnt <= 0xffff);
388 assert!(hcnt >= 8);
389 assert!(lcnt >= 8);
390
391 // Per I2C-bus specification a device in standard or fast mode must
392 // internally provide a hold time of at least 300ns for the SDA
393 // signal to bridge the undefined region of the falling edge of SCL.
394 // A smaller hold time of 120ns is used for fast mode plus.
395 let sda_tx_hold_count = if config.frequency < 1_000_000 {
396 // sda_tx_hold_count = clk_base [cycles/s] * 300ns * (1s /
397 // 1e9ns) Reduce 300/1e9 to 3/1e7 to avoid numbers that don't
398 // fit in uint. Add 1 to avoid division truncation.
399 ((clk_base * 3) / 10_000_000) + 1
400 } else {
401 // fast mode plus requires a clk_base > 32MHz
402 assert!(clk_base >= 32_000_000);
380 403
381 // Configure baudrate 404 // sda_tx_hold_count = clk_base [cycles/s] * 120ns * (1s /
382 405 // 1e9ns) Reduce 120/1e9 to 3/25e6 to avoid numbers that don't
383 // There are some subtleties to I2C timing which we are completely 406 // fit in uint. Add 1 to avoid division truncation.
384 // ignoring here See: 407 ((clk_base * 3) / 25_000_000) + 1
385 // https://github.com/raspberrypi/pico-sdk/blob/bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7/src/rp2_common/hardware_i2c/i2c.c#L69 408 };
386 let clk_base = crate::clocks::clk_peri_freq(); 409 assert!(sda_tx_hold_count <= lcnt - 2);
387
388 let period = (clk_base + config.frequency / 2) / config.frequency;
389 let lcnt = period * 3 / 5; // spend 3/5 (60%) of the period low
390 let hcnt = period - lcnt; // and 2/5 (40%) of the period high
391
392 // Check for out-of-range divisors:
393 assert!(hcnt <= 0xffff);
394 assert!(lcnt <= 0xffff);
395 assert!(hcnt >= 8);
396 assert!(lcnt >= 8);
397
398 // Per I2C-bus specification a device in standard or fast mode must
399 // internally provide a hold time of at least 300ns for the SDA
400 // signal to bridge the undefined region of the falling edge of SCL.
401 // A smaller hold time of 120ns is used for fast mode plus.
402 let sda_tx_hold_count = if config.frequency < 1_000_000 {
403 // sda_tx_hold_count = clk_base [cycles/s] * 300ns * (1s /
404 // 1e9ns) Reduce 300/1e9 to 3/1e7 to avoid numbers that don't
405 // fit in uint. Add 1 to avoid division truncation.
406 ((clk_base * 3) / 10_000_000) + 1
407 } else {
408 // fast mode plus requires a clk_base > 32MHz
409 assert!(clk_base >= 32_000_000);
410 410
411 // sda_tx_hold_count = clk_base [cycles/s] * 120ns * (1s / 411 p.ic_fs_scl_hcnt().write(|w| w.set_ic_fs_scl_hcnt(hcnt as u16));
412 // 1e9ns) Reduce 120/1e9 to 3/25e6 to avoid numbers that don't 412 p.ic_fs_scl_lcnt().write(|w| w.set_ic_fs_scl_lcnt(lcnt as u16));
413 // fit in uint. Add 1 to avoid division truncation. 413 p.ic_fs_spklen()
414 ((clk_base * 3) / 25_000_000) + 1 414 .write(|w| w.set_ic_fs_spklen(if lcnt < 16 { 1 } else { (lcnt / 16) as u8 }));
415 }; 415 p.ic_sda_hold()
416 assert!(sda_tx_hold_count <= lcnt - 2); 416 .modify(|w| w.set_ic_sda_tx_hold(sda_tx_hold_count as u16));
417 417
418 p.ic_fs_scl_hcnt().write(|w| w.set_ic_fs_scl_hcnt(hcnt as u16)); 418 // Enable I2C block
419 p.ic_fs_scl_lcnt().write(|w| w.set_ic_fs_scl_lcnt(lcnt as u16)); 419 p.ic_enable().write(|w| w.set_enable(true));
420 p.ic_fs_spklen()
421 .write(|w| w.set_ic_fs_spklen(if lcnt < 16 { 1 } else { (lcnt / 16) as u8 }));
422 p.ic_sda_hold()
423 .modify(|w| w.set_ic_sda_tx_hold(sda_tx_hold_count as u16));
424
425 // Enable I2C block
426 p.ic_enable().write(|w| w.set_enable(true));
427 }
428 420
429 Self { phantom: PhantomData } 421 Self { phantom: PhantomData }
430 } 422 }
@@ -439,11 +431,9 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
439 } 431 }
440 432
441 let p = T::regs(); 433 let p = T::regs();
442 unsafe { 434 p.ic_enable().write(|w| w.set_enable(false));
443 p.ic_enable().write(|w| w.set_enable(false)); 435 p.ic_tar().write(|w| w.set_ic_tar(addr));
444 p.ic_tar().write(|w| w.set_ic_tar(addr)); 436 p.ic_enable().write(|w| w.set_enable(true));
445 p.ic_enable().write(|w| w.set_enable(true));
446 }
447 Ok(()) 437 Ok(())
448 } 438 }
449 439
@@ -455,40 +445,38 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
455 #[inline] 445 #[inline]
456 fn tx_fifo_capacity() -> u8 { 446 fn tx_fifo_capacity() -> u8 {
457 let p = T::regs(); 447 let p = T::regs();
458 unsafe { FIFO_SIZE - p.ic_txflr().read().txflr() } 448 FIFO_SIZE - p.ic_txflr().read().txflr()
459 } 449 }
460 450
461 #[inline] 451 #[inline]
462 fn rx_fifo_len() -> u8 { 452 fn rx_fifo_len() -> u8 {
463 let p = T::regs(); 453 let p = T::regs();
464 unsafe { p.ic_rxflr().read().rxflr() } 454 p.ic_rxflr().read().rxflr()
465 } 455 }
466 456
467 fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> { 457 fn read_and_clear_abort_reason(&mut self) -> Result<(), Error> {
468 let p = T::regs(); 458 let p = T::regs();
469 unsafe { 459 let abort_reason = p.ic_tx_abrt_source().read();
470 let abort_reason = p.ic_tx_abrt_source().read(); 460 if abort_reason.0 != 0 {
471 if abort_reason.0 != 0 { 461 // Note clearing the abort flag also clears the reason, and this
472 // Note clearing the abort flag also clears the reason, and this 462 // instance of flag is clear-on-read! Note also the
473 // instance of flag is clear-on-read! Note also the 463 // IC_CLR_TX_ABRT register always reads as 0.
474 // IC_CLR_TX_ABRT register always reads as 0. 464 p.ic_clr_tx_abrt().read();
475 p.ic_clr_tx_abrt().read(); 465
476 466 let reason = if abort_reason.abrt_7b_addr_noack()
477 let reason = if abort_reason.abrt_7b_addr_noack() 467 | abort_reason.abrt_10addr1_noack()
478 | abort_reason.abrt_10addr1_noack() 468 | abort_reason.abrt_10addr2_noack()
479 | abort_reason.abrt_10addr2_noack() 469 {
480 { 470 AbortReason::NoAcknowledge
481 AbortReason::NoAcknowledge 471 } else if abort_reason.arb_lost() {
482 } else if abort_reason.arb_lost() { 472 AbortReason::ArbitrationLoss
483 AbortReason::ArbitrationLoss
484 } else {
485 AbortReason::Other(abort_reason.0)
486 };
487
488 Err(Error::Abort(reason))
489 } else { 473 } else {
490 Ok(()) 474 AbortReason::Other(abort_reason.0)
491 } 475 };
476
477 Err(Error::Abort(reason))
478 } else {
479 Ok(())
492 } 480 }
493 } 481 }
494 482
@@ -503,24 +491,21 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
503 let first = i == 0; 491 let first = i == 0;
504 let last = i == lastindex; 492 let last = i == lastindex;
505 493
506 // NOTE(unsafe) We have &mut self 494 // wait until there is space in the FIFO to write the next byte
507 unsafe { 495 while Self::tx_fifo_full() {}
508 // wait until there is space in the FIFO to write the next byte
509 while Self::tx_fifo_full() {}
510
511 p.ic_data_cmd().write(|w| {
512 w.set_restart(restart && first);
513 w.set_stop(send_stop && last);
514 496
515 w.set_cmd(true); 497 p.ic_data_cmd().write(|w| {
516 }); 498 w.set_restart(restart && first);
499 w.set_stop(send_stop && last);
517 500
518 while Self::rx_fifo_len() == 0 { 501 w.set_cmd(true);
519 self.read_and_clear_abort_reason()?; 502 });
520 }
521 503
522 *byte = p.ic_data_cmd().read().dat(); 504 while Self::rx_fifo_len() == 0 {
505 self.read_and_clear_abort_reason()?;
523 } 506 }
507
508 *byte = p.ic_data_cmd().read().dat();
524 } 509 }
525 510
526 Ok(()) 511 Ok(())
@@ -536,36 +521,33 @@ impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
536 for (i, byte) in write.iter().enumerate() { 521 for (i, byte) in write.iter().enumerate() {
537 let last = i == write.len() - 1; 522 let last = i == write.len() - 1;
538 523
539 // NOTE(unsafe) We have &mut self 524 p.ic_data_cmd().write(|w| {
540 unsafe { 525 w.set_stop(send_stop && last);
541 p.ic_data_cmd().write(|w| { 526 w.set_dat(*byte);
542 w.set_stop(send_stop && last); 527 });
543 w.set_dat(*byte);
544 });
545 528
546 // Wait until the transmission of the address/data from the 529 // Wait until the transmission of the address/data from the
547 // internal shift register has completed. For this to function 530 // internal shift register has completed. For this to function
548 // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The 531 // correctly, the TX_EMPTY_CTRL flag in IC_CON must be set. The
549 // TX_EMPTY_CTRL flag was set in i2c_init. 532 // TX_EMPTY_CTRL flag was set in i2c_init.
550 while !p.ic_raw_intr_stat().read().tx_empty() {} 533 while !p.ic_raw_intr_stat().read().tx_empty() {}
551 534
552 let abort_reason = self.read_and_clear_abort_reason(); 535 let abort_reason = self.read_and_clear_abort_reason();
553 536
554 if abort_reason.is_err() || (send_stop && last) { 537 if abort_reason.is_err() || (send_stop && last) {
555 // If the transaction was aborted or if it completed 538 // If the transaction was aborted or if it completed
556 // successfully wait until the STOP condition has occurred. 539 // successfully wait until the STOP condition has occurred.
557 540
558 while !p.ic_raw_intr_stat().read().stop_det() {} 541 while !p.ic_raw_intr_stat().read().stop_det() {}
559 542
560 p.ic_clr_stop_det().read().clr_stop_det(); 543 p.ic_clr_stop_det().read().clr_stop_det();
561 }
562
563 // Note the hardware issues a STOP automatically on an abort
564 // condition. Note also the hardware clears RX FIFO as well as
565 // TX on abort, ecause we set hwparam
566 // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0.
567 abort_reason?;
568 } 544 }
545
546 // Note the hardware issues a STOP automatically on an abort
547 // condition. Note also the hardware clears RX FIFO as well as
548 // TX on abort, ecause we set hwparam
549 // IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT to 0.
550 abort_reason?;
569 } 551 }
570 Ok(()) 552 Ok(())
571 } 553 }
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index d6f73219f..4fd3cb46a 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -261,33 +261,39 @@ pub fn init(config: config::Config) -> Peripherals {
261 261
262/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. 262/// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes.
263trait RegExt<T: Copy> { 263trait RegExt<T: Copy> {
264 unsafe fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; 264 fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
265 unsafe fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; 265 fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
266 unsafe fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R; 266 fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R;
267} 267}
268 268
269impl<T: Default + Copy, A: pac::common::Write> RegExt<T> for pac::common::Reg<T, A> { 269impl<T: Default + Copy, A: pac::common::Write> RegExt<T> for pac::common::Reg<T, A> {
270 unsafe fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R { 270 fn write_xor<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
271 let mut val = Default::default(); 271 let mut val = Default::default();
272 let res = f(&mut val); 272 let res = f(&mut val);
273 let ptr = (self.ptr() as *mut u8).add(0x1000) as *mut T; 273 unsafe {
274 ptr.write_volatile(val); 274 let ptr = (self.as_ptr() as *mut u8).add(0x1000) as *mut T;
275 ptr.write_volatile(val);
276 }
275 res 277 res
276 } 278 }
277 279
278 unsafe fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R { 280 fn write_set<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
279 let mut val = Default::default(); 281 let mut val = Default::default();
280 let res = f(&mut val); 282 let res = f(&mut val);
281 let ptr = (self.ptr() as *mut u8).add(0x2000) as *mut T; 283 unsafe {
282 ptr.write_volatile(val); 284 let ptr = (self.as_ptr() as *mut u8).add(0x2000) as *mut T;
285 ptr.write_volatile(val);
286 }
283 res 287 res
284 } 288 }
285 289
286 unsafe fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R { 290 fn write_clear<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
287 let mut val = Default::default(); 291 let mut val = Default::default();
288 let res = f(&mut val); 292 let res = f(&mut val);
289 let ptr = (self.ptr() as *mut u8).add(0x3000) as *mut T; 293 unsafe {
290 ptr.write_volatile(val); 294 let ptr = (self.as_ptr() as *mut u8).add(0x3000) as *mut T;
295 ptr.write_volatile(val);
296 }
291 res 297 res
292 } 298 }
293} 299}
diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs
index 2a7e4822a..468e8470a 100644
--- a/embassy-rp/src/multicore.rs
+++ b/embassy-rp/src/multicore.rs
@@ -163,14 +163,12 @@ where
163 } 163 }
164 164
165 // Reset the core 165 // Reset the core
166 unsafe { 166 let psm = pac::PSM;
167 let psm = pac::PSM; 167 psm.frce_off().modify(|w| w.set_proc1(true));
168 psm.frce_off().modify(|w| w.set_proc1(true)); 168 while !psm.frce_off().read().proc1() {
169 while !psm.frce_off().read().proc1() { 169 cortex_m::asm::nop();
170 cortex_m::asm::nop();
171 }
172 psm.frce_off().modify(|w| w.set_proc1(false));
173 } 170 }
171 psm.frce_off().modify(|w| w.set_proc1(false));
174 172
175 // The ARM AAPCS ABI requires 8-byte stack alignment. 173 // The ARM AAPCS ABI requires 8-byte stack alignment.
176 // #[align] on `struct Stack` ensures the bottom is aligned, but the top could still be 174 // #[align] on `struct Stack` ensures the bottom is aligned, but the top could still be
@@ -270,14 +268,12 @@ pub fn resume_core1() {
270// Push a value to the inter-core FIFO, block until space is available 268// Push a value to the inter-core FIFO, block until space is available
271#[inline(always)] 269#[inline(always)]
272fn fifo_write(value: u32) { 270fn fifo_write(value: u32) {
273 unsafe { 271 let sio = pac::SIO;
274 let sio = pac::SIO; 272 // Wait for the FIFO to have enough space
275 // Wait for the FIFO to have enough space 273 while !sio.fifo().st().read().rdy() {
276 while !sio.fifo().st().read().rdy() { 274 cortex_m::asm::nop();
277 cortex_m::asm::nop();
278 }
279 sio.fifo().wr().write_value(value);
280 } 275 }
276 sio.fifo().wr().write_value(value);
281 // Fire off an event to the other core. 277 // Fire off an event to the other core.
282 // This is required as the other core may be `wfe` (waiting for event) 278 // This is required as the other core may be `wfe` (waiting for event)
283 cortex_m::asm::sev(); 279 cortex_m::asm::sev();
@@ -286,38 +282,32 @@ fn fifo_write(value: u32) {
286// Pop a value from inter-core FIFO, block until available 282// Pop a value from inter-core FIFO, block until available
287#[inline(always)] 283#[inline(always)]
288fn fifo_read() -> u32 { 284fn fifo_read() -> u32 {
289 unsafe { 285 let sio = pac::SIO;
290 let sio = pac::SIO; 286 // Wait until FIFO has data
291 // Wait until FIFO has data 287 while !sio.fifo().st().read().vld() {
292 while !sio.fifo().st().read().vld() { 288 cortex_m::asm::nop();
293 cortex_m::asm::nop();
294 }
295 sio.fifo().rd().read()
296 } 289 }
290 sio.fifo().rd().read()
297} 291}
298 292
299// Pop a value from inter-core FIFO, `wfe` until available 293// Pop a value from inter-core FIFO, `wfe` until available
300#[inline(always)] 294#[inline(always)]
301#[allow(unused)] 295#[allow(unused)]
302fn fifo_read_wfe() -> u32 { 296fn fifo_read_wfe() -> u32 {
303 unsafe { 297 let sio = pac::SIO;
304 let sio = pac::SIO; 298 // Wait until FIFO has data
305 // Wait until FIFO has data 299 while !sio.fifo().st().read().vld() {
306 while !sio.fifo().st().read().vld() { 300 cortex_m::asm::wfe();
307 cortex_m::asm::wfe();
308 }
309 sio.fifo().rd().read()
310 } 301 }
302 sio.fifo().rd().read()
311} 303}
312 304
313// Drain inter-core FIFO 305// Drain inter-core FIFO
314#[inline(always)] 306#[inline(always)]
315fn fifo_drain() { 307fn fifo_drain() {
316 unsafe { 308 let sio = pac::SIO;
317 let sio = pac::SIO; 309 while sio.fifo().st().read().vld() {
318 while sio.fifo().st().read().vld() { 310 let _ = sio.fifo().rd().read();
319 let _ = sio.fifo().rd().read();
320 }
321 } 311 }
322} 312}
323 313
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 0fa3bd771..1b36e0a54 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -87,7 +87,7 @@ const SMIRQ_MASK: u32 = 1 << 8;
87 87
88#[cfg(feature = "rt")] 88#[cfg(feature = "rt")]
89#[interrupt] 89#[interrupt]
90unsafe fn PIO0_IRQ_0() { 90fn PIO0_IRQ_0() {
91 use crate::pac; 91 use crate::pac;
92 let ints = pac::PIO0.irqs(0).ints().read().0; 92 let ints = pac::PIO0.irqs(0).ints().read().0;
93 for bit in 0..12 { 93 for bit in 0..12 {
@@ -100,7 +100,7 @@ unsafe fn PIO0_IRQ_0() {
100 100
101#[cfg(feature = "rt")] 101#[cfg(feature = "rt")]
102#[interrupt] 102#[interrupt]
103unsafe fn PIO1_IRQ_0() { 103fn PIO1_IRQ_0() {
104 use crate::pac; 104 use crate::pac;
105 let ints = pac::PIO1.irqs(0).ints().read().0; 105 let ints = pac::PIO1.irqs(0).ints().read().0;
106 for bit in 0..12 { 106 for bit in 0..12 {
@@ -145,11 +145,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI
145 Poll::Ready(()) 145 Poll::Ready(())
146 } else { 146 } else {
147 WAKERS[PIO::PIO_NO as usize].fifo_out()[SM].register(cx.waker()); 147 WAKERS[PIO::PIO_NO as usize].fifo_out()[SM].register(cx.waker());
148 unsafe { 148 PIO::PIO.irqs(0).inte().write_set(|m| {
149 PIO::PIO.irqs(0).inte().write_set(|m| { 149 m.0 = TXNFULL_MASK << SM;
150 m.0 = TXNFULL_MASK << SM; 150 });
151 });
152 }
153 // debug!("Pending"); 151 // debug!("Pending");
154 Poll::Pending 152 Poll::Pending
155 } 153 }
@@ -158,11 +156,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI
158 156
159impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoOutFuture<'a, 'd, PIO, SM> { 157impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoOutFuture<'a, 'd, PIO, SM> {
160 fn drop(&mut self) { 158 fn drop(&mut self) {
161 unsafe { 159 PIO::PIO.irqs(0).inte().write_clear(|m| {
162 PIO::PIO.irqs(0).inte().write_clear(|m| { 160 m.0 = TXNFULL_MASK << SM;
163 m.0 = TXNFULL_MASK << SM; 161 });
164 });
165 }
166 } 162 }
167} 163}
168 164
@@ -186,11 +182,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO
186 Poll::Ready(v) 182 Poll::Ready(v)
187 } else { 183 } else {
188 WAKERS[PIO::PIO_NO as usize].fifo_in()[SM].register(cx.waker()); 184 WAKERS[PIO::PIO_NO as usize].fifo_in()[SM].register(cx.waker());
189 unsafe { 185 PIO::PIO.irqs(0).inte().write_set(|m| {
190 PIO::PIO.irqs(0).inte().write_set(|m| { 186 m.0 = RXNEMPTY_MASK << SM;
191 m.0 = RXNEMPTY_MASK << SM; 187 });
192 });
193 }
194 //debug!("Pending"); 188 //debug!("Pending");
195 Poll::Pending 189 Poll::Pending
196 } 190 }
@@ -199,11 +193,9 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO
199 193
200impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoInFuture<'a, 'd, PIO, SM> { 194impl<'a, 'd, PIO: Instance, const SM: usize> Drop for FifoInFuture<'a, 'd, PIO, SM> {
201 fn drop(&mut self) { 195 fn drop(&mut self) {
202 unsafe { 196 PIO::PIO.irqs(0).inte().write_clear(|m| {
203 PIO::PIO.irqs(0).inte().write_clear(|m| { 197 m.0 = RXNEMPTY_MASK << SM;
204 m.0 = RXNEMPTY_MASK << SM; 198 });
205 });
206 }
207 } 199 }
208} 200}
209 201
@@ -220,30 +212,24 @@ impl<'a, 'd, PIO: Instance> Future for IrqFuture<'a, 'd, PIO> {
220 //debug!("Poll {},{}", PIO::PIO_NO, SM); 212 //debug!("Poll {},{}", PIO::PIO_NO, SM);
221 213
222 // Check if IRQ flag is already set 214 // Check if IRQ flag is already set
223 if unsafe { PIO::PIO.irq().read().0 & (1 << self.irq_no) != 0 } { 215 if PIO::PIO.irq().read().0 & (1 << self.irq_no) != 0 {
224 unsafe { 216 PIO::PIO.irq().write(|m| m.0 = 1 << self.irq_no);
225 PIO::PIO.irq().write(|m| m.0 = 1 << self.irq_no);
226 }
227 return Poll::Ready(()); 217 return Poll::Ready(());
228 } 218 }
229 219
230 WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker()); 220 WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker());
231 unsafe { 221 PIO::PIO.irqs(0).inte().write_set(|m| {
232 PIO::PIO.irqs(0).inte().write_set(|m| { 222 m.0 = SMIRQ_MASK << self.irq_no;
233 m.0 = SMIRQ_MASK << self.irq_no; 223 });
234 });
235 }
236 Poll::Pending 224 Poll::Pending
237 } 225 }
238} 226}
239 227
240impl<'a, 'd, PIO: Instance> Drop for IrqFuture<'a, 'd, PIO> { 228impl<'a, 'd, PIO: Instance> Drop for IrqFuture<'a, 'd, PIO> {
241 fn drop(&mut self) { 229 fn drop(&mut self) {
242 unsafe { 230 PIO::PIO.irqs(0).inte().write_clear(|m| {
243 PIO::PIO.irqs(0).inte().write_clear(|m| { 231 m.0 = SMIRQ_MASK << self.irq_no;
244 m.0 = SMIRQ_MASK << self.irq_no; 232 });
245 });
246 }
247 } 233 }
248} 234}
249 235
@@ -256,57 +242,47 @@ impl<'l, PIO: Instance> Pin<'l, PIO> {
256 /// Set the pin's drive strength. 242 /// Set the pin's drive strength.
257 #[inline] 243 #[inline]
258 pub fn set_drive_strength(&mut self, strength: Drive) { 244 pub fn set_drive_strength(&mut self, strength: Drive) {
259 unsafe { 245 self.pin.pad_ctrl().modify(|w| {
260 self.pin.pad_ctrl().modify(|w| { 246 w.set_drive(match strength {
261 w.set_drive(match strength { 247 Drive::_2mA => pac::pads::vals::Drive::_2MA,
262 Drive::_2mA => pac::pads::vals::Drive::_2MA, 248 Drive::_4mA => pac::pads::vals::Drive::_4MA,
263 Drive::_4mA => pac::pads::vals::Drive::_4MA, 249 Drive::_8mA => pac::pads::vals::Drive::_8MA,
264 Drive::_8mA => pac::pads::vals::Drive::_8MA, 250 Drive::_12mA => pac::pads::vals::Drive::_12MA,
265 Drive::_12mA => pac::pads::vals::Drive::_12MA,
266 });
267 }); 251 });
268 } 252 });
269 } 253 }
270 254
271 // Set the pin's slew rate. 255 // Set the pin's slew rate.
272 #[inline] 256 #[inline]
273 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) { 257 pub fn set_slew_rate(&mut self, slew_rate: SlewRate) {
274 unsafe { 258 self.pin.pad_ctrl().modify(|w| {
275 self.pin.pad_ctrl().modify(|w| { 259 w.set_slewfast(slew_rate == SlewRate::Fast);
276 w.set_slewfast(slew_rate == SlewRate::Fast); 260 });
277 });
278 }
279 } 261 }
280 262
281 /// Set the pin's pull. 263 /// Set the pin's pull.
282 #[inline] 264 #[inline]
283 pub fn set_pull(&mut self, pull: Pull) { 265 pub fn set_pull(&mut self, pull: Pull) {
284 unsafe { 266 self.pin.pad_ctrl().modify(|w| {
285 self.pin.pad_ctrl().modify(|w| { 267 w.set_pue(pull == Pull::Up);
286 w.set_pue(pull == Pull::Up); 268 w.set_pde(pull == Pull::Down);
287 w.set_pde(pull == Pull::Down); 269 });
288 });
289 }
290 } 270 }
291 271
292 /// Set the pin's schmitt trigger. 272 /// Set the pin's schmitt trigger.
293 #[inline] 273 #[inline]
294 pub fn set_schmitt(&mut self, enable: bool) { 274 pub fn set_schmitt(&mut self, enable: bool) {
295 unsafe { 275 self.pin.pad_ctrl().modify(|w| {
296 self.pin.pad_ctrl().modify(|w| { 276 w.set_schmitt(enable);
297 w.set_schmitt(enable); 277 });
298 });
299 }
300 } 278 }
301 279
302 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) { 280 pub fn set_input_sync_bypass<'a>(&mut self, bypass: bool) {
303 let mask = 1 << self.pin(); 281 let mask = 1 << self.pin();
304 unsafe { 282 if bypass {
305 if bypass { 283 PIO::PIO.input_sync_bypass().write_set(|w| *w = mask);
306 PIO::PIO.input_sync_bypass().write_set(|w| *w = mask); 284 } else {
307 } else { 285 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask);
308 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask);
309 }
310 } 286 }
311 } 287 }
312 288
@@ -321,41 +297,37 @@ pub struct StateMachineRx<'d, PIO: Instance, const SM: usize> {
321 297
322impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> { 298impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
323 pub fn empty(&self) -> bool { 299 pub fn empty(&self) -> bool {
324 unsafe { PIO::PIO.fstat().read().rxempty() & (1u8 << SM) != 0 } 300 PIO::PIO.fstat().read().rxempty() & (1u8 << SM) != 0
325 } 301 }
326 302
327 pub fn full(&self) -> bool { 303 pub fn full(&self) -> bool {
328 unsafe { PIO::PIO.fstat().read().rxfull() & (1u8 << SM) != 0 } 304 PIO::PIO.fstat().read().rxfull() & (1u8 << SM) != 0
329 } 305 }
330 306
331 pub fn level(&self) -> u8 { 307 pub fn level(&self) -> u8 {
332 unsafe { (PIO::PIO.flevel().read().0 >> (SM * 8 + 4)) as u8 & 0x0f } 308 (PIO::PIO.flevel().read().0 >> (SM * 8 + 4)) as u8 & 0x0f
333 } 309 }
334 310
335 pub fn stalled(&self) -> bool { 311 pub fn stalled(&self) -> bool {
336 unsafe { 312 let fdebug = PIO::PIO.fdebug();
337 let fdebug = PIO::PIO.fdebug(); 313 let ret = fdebug.read().rxstall() & (1 << SM) != 0;
338 let ret = fdebug.read().rxstall() & (1 << SM) != 0; 314 if ret {
339 if ret { 315 fdebug.write(|w| w.set_rxstall(1 << SM));
340 fdebug.write(|w| w.set_rxstall(1 << SM));
341 }
342 ret
343 } 316 }
317 ret
344 } 318 }
345 319
346 pub fn underflowed(&self) -> bool { 320 pub fn underflowed(&self) -> bool {
347 unsafe { 321 let fdebug = PIO::PIO.fdebug();
348 let fdebug = PIO::PIO.fdebug(); 322 let ret = fdebug.read().rxunder() & (1 << SM) != 0;
349 let ret = fdebug.read().rxunder() & (1 << SM) != 0; 323 if ret {
350 if ret { 324 fdebug.write(|w| w.set_rxunder(1 << SM));
351 fdebug.write(|w| w.set_rxunder(1 << SM));
352 }
353 ret
354 } 325 }
326 ret
355 } 327 }
356 328
357 pub fn pull(&mut self) -> u32 { 329 pub fn pull(&mut self) -> u32 {
358 unsafe { PIO::PIO.rxf(SM).read() } 330 PIO::PIO.rxf(SM).read()
359 } 331 }
360 332
361 pub fn try_pull(&mut self) -> Option<u32> { 333 pub fn try_pull(&mut self) -> Option<u32> {
@@ -374,24 +346,22 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
374 ch: PeripheralRef<'a, C>, 346 ch: PeripheralRef<'a, C>,
375 data: &'a mut [W], 347 data: &'a mut [W],
376 ) -> Transfer<'a, C> { 348 ) -> Transfer<'a, C> {
377 unsafe { 349 let pio_no = PIO::PIO_NO;
378 let pio_no = PIO::PIO_NO; 350 let p = ch.regs();
379 let p = ch.regs(); 351 p.write_addr().write_value(data.as_ptr() as u32);
380 p.write_addr().write_value(data.as_ptr() as u32); 352 p.read_addr().write_value(PIO::PIO.rxf(SM).as_ptr() as u32);
381 p.read_addr().write_value(PIO::PIO.rxf(SM).ptr() as u32); 353 p.trans_count().write_value(data.len() as u32);
382 p.trans_count().write_value(data.len() as u32); 354 compiler_fence(Ordering::SeqCst);
383 compiler_fence(Ordering::SeqCst); 355 p.ctrl_trig().write(|w| {
384 p.ctrl_trig().write(|w| { 356 // Set RX DREQ for this statemachine
385 // Set RX DREQ for this statemachine 357 w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8 + 4));
386 w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8 + 4)); 358 w.set_data_size(W::size());
387 w.set_data_size(W::size()); 359 w.set_chain_to(ch.number());
388 w.set_chain_to(ch.number()); 360 w.set_incr_read(false);
389 w.set_incr_read(false); 361 w.set_incr_write(true);
390 w.set_incr_write(true); 362 w.set_en(true);
391 w.set_en(true); 363 });
392 }); 364 compiler_fence(Ordering::SeqCst);
393 compiler_fence(Ordering::SeqCst);
394 }
395 Transfer::new(ch) 365 Transfer::new(ch)
396 } 366 }
397} 367}
@@ -402,42 +372,36 @@ pub struct StateMachineTx<'d, PIO: Instance, const SM: usize> {
402 372
403impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> { 373impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
404 pub fn empty(&self) -> bool { 374 pub fn empty(&self) -> bool {
405 unsafe { PIO::PIO.fstat().read().txempty() & (1u8 << SM) != 0 } 375 PIO::PIO.fstat().read().txempty() & (1u8 << SM) != 0
406 } 376 }
407 pub fn full(&self) -> bool { 377 pub fn full(&self) -> bool {
408 unsafe { PIO::PIO.fstat().read().txfull() & (1u8 << SM) != 0 } 378 PIO::PIO.fstat().read().txfull() & (1u8 << SM) != 0
409 } 379 }
410 380
411 pub fn level(&self) -> u8 { 381 pub fn level(&self) -> u8 {
412 unsafe { (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f } 382 (PIO::PIO.flevel().read().0 >> (SM * 8)) as u8 & 0x0f
413 } 383 }
414 384
415 pub fn stalled(&self) -> bool { 385 pub fn stalled(&self) -> bool {
416 unsafe { 386 let fdebug = PIO::PIO.fdebug();
417 let fdebug = PIO::PIO.fdebug(); 387 let ret = fdebug.read().txstall() & (1 << SM) != 0;
418 let ret = fdebug.read().txstall() & (1 << SM) != 0; 388 if ret {
419 if ret { 389 fdebug.write(|w| w.set_txstall(1 << SM));
420 fdebug.write(|w| w.set_txstall(1 << SM));
421 }
422 ret
423 } 390 }
391 ret
424 } 392 }
425 393
426 pub fn overflowed(&self) -> bool { 394 pub fn overflowed(&self) -> bool {
427 unsafe { 395 let fdebug = PIO::PIO.fdebug();
428 let fdebug = PIO::PIO.fdebug(); 396 let ret = fdebug.read().txover() & (1 << SM) != 0;
429 let ret = fdebug.read().txover() & (1 << SM) != 0; 397 if ret {
430 if ret { 398 fdebug.write(|w| w.set_txover(1 << SM));
431 fdebug.write(|w| w.set_txover(1 << SM));
432 }
433 ret
434 } 399 }
400 ret
435 } 401 }
436 402
437 pub fn push(&mut self, v: u32) { 403 pub fn push(&mut self, v: u32) {
438 unsafe { 404 PIO::PIO.txf(SM).write_value(v);
439 PIO::PIO.txf(SM).write_value(v);
440 }
441 } 405 }
442 406
443 pub fn try_push(&mut self, v: u32) -> bool { 407 pub fn try_push(&mut self, v: u32) -> bool {
@@ -453,24 +417,22 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
453 } 417 }
454 418
455 pub fn dma_push<'a, C: Channel, W: Word>(&'a mut self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> { 419 pub fn dma_push<'a, C: Channel, W: Word>(&'a mut self, ch: PeripheralRef<'a, C>, data: &'a [W]) -> Transfer<'a, C> {
456 unsafe { 420 let pio_no = PIO::PIO_NO;
457 let pio_no = PIO::PIO_NO; 421 let p = ch.regs();
458 let p = ch.regs(); 422 p.read_addr().write_value(data.as_ptr() as u32);
459 p.read_addr().write_value(data.as_ptr() as u32); 423 p.write_addr().write_value(PIO::PIO.txf(SM).as_ptr() as u32);
460 p.write_addr().write_value(PIO::PIO.txf(SM).ptr() as u32); 424 p.trans_count().write_value(data.len() as u32);
461 p.trans_count().write_value(data.len() as u32); 425 compiler_fence(Ordering::SeqCst);
462 compiler_fence(Ordering::SeqCst); 426 p.ctrl_trig().write(|w| {
463 p.ctrl_trig().write(|w| { 427 // Set TX DREQ for this statemachine
464 // Set TX DREQ for this statemachine 428 w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8));
465 w.set_treq_sel(TreqSel(pio_no * 8 + SM as u8)); 429 w.set_data_size(W::size());
466 w.set_data_size(W::size()); 430 w.set_chain_to(ch.number());
467 w.set_chain_to(ch.number()); 431 w.set_incr_read(true);
468 w.set_incr_read(true); 432 w.set_incr_write(false);
469 w.set_incr_write(false); 433 w.set_en(true);
470 w.set_en(true); 434 });
471 }); 435 compiler_fence(Ordering::SeqCst);
472 compiler_fence(Ordering::SeqCst);
473 }
474 Transfer::new(ch) 436 Transfer::new(ch)
475 } 437 }
476} 438}
@@ -482,9 +444,7 @@ pub struct StateMachine<'d, PIO: Instance, const SM: usize> {
482 444
483impl<'d, PIO: Instance, const SM: usize> Drop for StateMachine<'d, PIO, SM> { 445impl<'d, PIO: Instance, const SM: usize> Drop for StateMachine<'d, PIO, SM> {
484 fn drop(&mut self) { 446 fn drop(&mut self) {
485 unsafe { 447 PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(1 << SM));
486 PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(1 << SM));
487 }
488 on_pio_drop::<PIO>(); 448 on_pio_drop::<PIO>();
489 } 449 }
490} 450}
@@ -647,45 +607,43 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
647 assert!(config.shift_in.threshold <= 32, "shift_in.threshold must be <= 32"); 607 assert!(config.shift_in.threshold <= 32, "shift_in.threshold must be <= 32");
648 assert!(config.shift_out.threshold <= 32, "shift_out.threshold must be <= 32"); 608 assert!(config.shift_out.threshold <= 32, "shift_out.threshold must be <= 32");
649 let sm = Self::this_sm(); 609 let sm = Self::this_sm();
650 unsafe { 610 sm.clkdiv().write(|w| w.0 = config.clock_divider.to_bits() << 8);
651 sm.clkdiv().write(|w| w.0 = config.clock_divider.to_bits() << 8); 611 sm.execctrl().write(|w| {
652 sm.execctrl().write(|w| { 612 w.set_side_en(config.exec.side_en);
653 w.set_side_en(config.exec.side_en); 613 w.set_side_pindir(config.exec.side_pindir);
654 w.set_side_pindir(config.exec.side_pindir); 614 w.set_jmp_pin(config.exec.jmp_pin);
655 w.set_jmp_pin(config.exec.jmp_pin); 615 w.set_out_en_sel(config.out_en_sel);
656 w.set_out_en_sel(config.out_en_sel); 616 w.set_inline_out_en(config.inline_out_en);
657 w.set_inline_out_en(config.inline_out_en); 617 w.set_out_sticky(config.out_sticky);
658 w.set_out_sticky(config.out_sticky); 618 w.set_wrap_top(config.exec.wrap_top);
659 w.set_wrap_top(config.exec.wrap_top); 619 w.set_wrap_bottom(config.exec.wrap_bottom);
660 w.set_wrap_bottom(config.exec.wrap_bottom); 620 w.set_status_sel(match config.status_sel {
661 w.set_status_sel(match config.status_sel { 621 StatusSource::TxFifoLevel => SmExecctrlStatusSel::TXLEVEL,
662 StatusSource::TxFifoLevel => SmExecctrlStatusSel::TXLEVEL, 622 StatusSource::RxFifoLevel => SmExecctrlStatusSel::RXLEVEL,
663 StatusSource::RxFifoLevel => SmExecctrlStatusSel::RXLEVEL,
664 });
665 w.set_status_n(config.status_n);
666 });
667 sm.shiftctrl().write(|w| {
668 w.set_fjoin_rx(config.fifo_join == FifoJoin::RxOnly);
669 w.set_fjoin_tx(config.fifo_join == FifoJoin::TxOnly);
670 w.set_pull_thresh(config.shift_out.threshold);
671 w.set_push_thresh(config.shift_in.threshold);
672 w.set_out_shiftdir(config.shift_out.direction == ShiftDirection::Right);
673 w.set_in_shiftdir(config.shift_in.direction == ShiftDirection::Right);
674 w.set_autopull(config.shift_out.auto_fill);
675 w.set_autopush(config.shift_in.auto_fill);
676 });
677 sm.pinctrl().write(|w| {
678 w.set_sideset_count(config.pins.sideset_count);
679 w.set_set_count(config.pins.set_count);
680 w.set_out_count(config.pins.out_count);
681 w.set_in_base(config.pins.in_base);
682 w.set_sideset_base(config.pins.sideset_base);
683 w.set_set_base(config.pins.set_base);
684 w.set_out_base(config.pins.out_base);
685 }); 623 });
686 if let Some(origin) = config.origin { 624 w.set_status_n(config.status_n);
687 pio_instr_util::exec_jmp(self, origin); 625 });
688 } 626 sm.shiftctrl().write(|w| {
627 w.set_fjoin_rx(config.fifo_join == FifoJoin::RxOnly);
628 w.set_fjoin_tx(config.fifo_join == FifoJoin::TxOnly);
629 w.set_pull_thresh(config.shift_out.threshold);
630 w.set_push_thresh(config.shift_in.threshold);
631 w.set_out_shiftdir(config.shift_out.direction == ShiftDirection::Right);
632 w.set_in_shiftdir(config.shift_in.direction == ShiftDirection::Right);
633 w.set_autopull(config.shift_out.auto_fill);
634 w.set_autopush(config.shift_in.auto_fill);
635 });
636 sm.pinctrl().write(|w| {
637 w.set_sideset_count(config.pins.sideset_count);
638 w.set_set_count(config.pins.set_count);
639 w.set_out_count(config.pins.out_count);
640 w.set_in_base(config.pins.in_base);
641 w.set_sideset_base(config.pins.sideset_base);
642 w.set_set_base(config.pins.set_base);
643 w.set_out_base(config.pins.out_base);
644 });
645 if let Some(origin) = config.origin {
646 unsafe { pio_instr_util::exec_jmp(self, origin) }
689 } 647 }
690 } 648 }
691 649
@@ -696,45 +654,35 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
696 654
697 pub fn restart(&mut self) { 655 pub fn restart(&mut self) {
698 let mask = 1u8 << SM; 656 let mask = 1u8 << SM;
699 unsafe { 657 PIO::PIO.ctrl().write_set(|w| w.set_sm_restart(mask));
700 PIO::PIO.ctrl().write_set(|w| w.set_sm_restart(mask));
701 }
702 } 658 }
703 pub fn set_enable(&mut self, enable: bool) { 659 pub fn set_enable(&mut self, enable: bool) {
704 let mask = 1u8 << SM; 660 let mask = 1u8 << SM;
705 unsafe { 661 if enable {
706 if enable { 662 PIO::PIO.ctrl().write_set(|w| w.set_sm_enable(mask));
707 PIO::PIO.ctrl().write_set(|w| w.set_sm_enable(mask)); 663 } else {
708 } else { 664 PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(mask));
709 PIO::PIO.ctrl().write_clear(|w| w.set_sm_enable(mask));
710 }
711 } 665 }
712 } 666 }
713 667
714 pub fn is_enabled(&self) -> bool { 668 pub fn is_enabled(&self) -> bool {
715 unsafe { PIO::PIO.ctrl().read().sm_enable() & (1u8 << SM) != 0 } 669 PIO::PIO.ctrl().read().sm_enable() & (1u8 << SM) != 0
716 } 670 }
717 671
718 pub fn clkdiv_restart(&mut self) { 672 pub fn clkdiv_restart(&mut self) {
719 let mask = 1u8 << SM; 673 let mask = 1u8 << SM;
720 unsafe { 674 PIO::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask));
721 PIO::PIO.ctrl().write_set(|w| w.set_clkdiv_restart(mask));
722 }
723 } 675 }
724 676
725 fn with_paused(&mut self, f: impl FnOnce(&mut Self)) { 677 fn with_paused(&mut self, f: impl FnOnce(&mut Self)) {
726 let enabled = self.is_enabled(); 678 let enabled = self.is_enabled();
727 self.set_enable(false); 679 self.set_enable(false);
728 let pincfg = unsafe { Self::this_sm().pinctrl().read() }; 680 let pincfg = Self::this_sm().pinctrl().read();
729 let execcfg = unsafe { Self::this_sm().execctrl().read() }; 681 let execcfg = Self::this_sm().execctrl().read();
730 unsafe { 682 Self::this_sm().execctrl().write_clear(|w| w.set_out_sticky(true));
731 Self::this_sm().execctrl().write_clear(|w| w.set_out_sticky(true));
732 }
733 f(self); 683 f(self);
734 unsafe { 684 Self::this_sm().pinctrl().write_value(pincfg);
735 Self::this_sm().pinctrl().write_value(pincfg); 685 Self::this_sm().execctrl().write_value(execcfg);
736 Self::this_sm().execctrl().write_value(execcfg);
737 }
738 self.set_enable(enabled); 686 self.set_enable(enabled);
739 } 687 }
740 688
@@ -743,14 +691,12 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
743 pub fn set_pin_dirs(&mut self, dir: Direction, pins: &[&Pin<'d, PIO>]) { 691 pub fn set_pin_dirs(&mut self, dir: Direction, pins: &[&Pin<'d, PIO>]) {
744 self.with_paused(|sm| { 692 self.with_paused(|sm| {
745 for pin in pins { 693 for pin in pins {
746 unsafe { 694 Self::this_sm().pinctrl().write(|w| {
747 Self::this_sm().pinctrl().write(|w| { 695 w.set_set_base(pin.pin());
748 w.set_set_base(pin.pin()); 696 w.set_set_count(1);
749 w.set_set_count(1); 697 });
750 }); 698 // SET PINDIRS, (dir)
751 // SET PINDIRS, (dir) 699 unsafe { sm.exec_instr(0b111_00000_100_00000 | dir as u16) };
752 sm.exec_instr(0b111_00000_100_00000 | dir as u16);
753 }
754 } 700 }
755 }); 701 });
756 } 702 }
@@ -760,29 +706,25 @@ impl<'d, PIO: Instance + 'd, const SM: usize> StateMachine<'d, PIO, SM> {
760 pub fn set_pins(&mut self, level: Level, pins: &[&Pin<'d, PIO>]) { 706 pub fn set_pins(&mut self, level: Level, pins: &[&Pin<'d, PIO>]) {
761 self.with_paused(|sm| { 707 self.with_paused(|sm| {
762 for pin in pins { 708 for pin in pins {
763 unsafe { 709 Self::this_sm().pinctrl().write(|w| {
764 Self::this_sm().pinctrl().write(|w| { 710 w.set_set_base(pin.pin());
765 w.set_set_base(pin.pin()); 711 w.set_set_count(1);
766 w.set_set_count(1); 712 });
767 }); 713 // SET PINS, (dir)
768 // SET PINS, (dir) 714 unsafe { sm.exec_instr(0b111_00000_000_00000 | level as u16) };
769 sm.exec_instr(0b111_00000_000_00000 | level as u16);
770 }
771 } 715 }
772 }); 716 });
773 } 717 }
774 718
775 pub fn clear_fifos(&mut self) { 719 pub fn clear_fifos(&mut self) {
776 // Toggle FJOIN_RX to flush FIFOs 720 // Toggle FJOIN_RX to flush FIFOs
777 unsafe { 721 let shiftctrl = Self::this_sm().shiftctrl();
778 let shiftctrl = Self::this_sm().shiftctrl(); 722 shiftctrl.modify(|w| {
779 shiftctrl.modify(|w| { 723 w.set_fjoin_rx(!w.fjoin_rx());
780 w.set_fjoin_rx(!w.fjoin_rx()); 724 });
781 }); 725 shiftctrl.modify(|w| {
782 shiftctrl.modify(|w| { 726 w.set_fjoin_rx(!w.fjoin_rx());
783 w.set_fjoin_rx(!w.fjoin_rx()); 727 });
784 });
785 }
786 } 728 }
787 729
788 pub unsafe fn exec_instr(&mut self, instr: u16) { 730 pub unsafe fn exec_instr(&mut self, instr: u16) {
@@ -856,11 +798,9 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
856 if (self.instructions_used | used_mask) & mask != 0 { 798 if (self.instructions_used | used_mask) & mask != 0 {
857 return Err(addr); 799 return Err(addr);
858 } 800 }
859 unsafe { 801 PIO::PIO.instr_mem(addr).write(|w| {
860 PIO::PIO.instr_mem(addr).write(|w| { 802 w.set_instr_mem(instr);
861 w.set_instr_mem(instr); 803 });
862 });
863 }
864 used_mask |= mask; 804 used_mask |= mask;
865 } 805 }
866 self.instructions_used |= used_mask; 806 self.instructions_used |= used_mask;
@@ -877,17 +817,15 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
877 } 817 }
878 818
879 pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) { 819 pub fn set_input_sync_bypass<'a>(&'a mut self, bypass: u32, mask: u32) {
880 unsafe { 820 // this can interfere with per-pin bypass functions. splitting the
881 // this can interfere with per-pin bypass functions. splitting the 821 // modification is going to be fine since nothing that relies on
882 // modification is going to be fine since nothing that relies on 822 // it can reasonably run before we finish.
883 // it can reasonably run before we finish. 823 PIO::PIO.input_sync_bypass().write_set(|w| *w = mask & bypass);
884 PIO::PIO.input_sync_bypass().write_set(|w| *w = mask & bypass); 824 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass);
885 PIO::PIO.input_sync_bypass().write_clear(|w| *w = mask & !bypass);
886 }
887 } 825 }
888 826
889 pub fn get_input_sync_bypass(&self) -> u32 { 827 pub fn get_input_sync_bypass(&self) -> u32 {
890 unsafe { PIO::PIO.input_sync_bypass().read() } 828 PIO::PIO.input_sync_bypass().read()
891 } 829 }
892 830
893 /// Register a pin for PIO usage. Pins will be released from the PIO block 831 /// 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> {
896 /// of [`Pio`] do not keep pin registrations alive.** 834 /// of [`Pio`] do not keep pin registrations alive.**
897 pub fn make_pio_pin(&mut self, pin: impl Peripheral<P = impl PioPin + 'd> + 'd) -> Pin<'d, PIO> { 835 pub fn make_pio_pin(&mut self, pin: impl Peripheral<P = impl PioPin + 'd> + 'd) -> Pin<'d, PIO> {
898 into_ref!(pin); 836 into_ref!(pin);
899 unsafe { 837 pin.io().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL.0));
900 pin.io().ctrl().write(|w| w.set_funcsel(PIO::FUNCSEL.0));
901 }
902 // we can be relaxed about this because we're &mut here and nothing is cached 838 // we can be relaxed about this because we're &mut here and nothing is cached
903 PIO::state().used_pins.fetch_or(1 << pin.pin_bank(), Ordering::Relaxed); 839 PIO::state().used_pins.fetch_or(1 << pin.pin_bank(), Ordering::Relaxed);
904 Pin { 840 Pin {
@@ -916,13 +852,11 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
916 _pio: PhantomData, 852 _pio: PhantomData,
917 }; 853 };
918 f(&mut batch); 854 f(&mut batch);
919 unsafe { 855 PIO::PIO.ctrl().modify(|w| {
920 PIO::PIO.ctrl().modify(|w| { 856 w.set_clkdiv_restart(batch.clkdiv_restart);
921 w.set_clkdiv_restart(batch.clkdiv_restart); 857 w.set_sm_restart(batch.sm_restart);
922 w.set_sm_restart(batch.sm_restart); 858 w.set_sm_enable((w.sm_enable() & !batch.sm_enable_mask) | batch.sm_enable);
923 w.set_sm_enable((w.sm_enable() & !batch.sm_enable_mask) | batch.sm_enable); 859 });
924 });
925 }
926 } 860 }
927} 861}
928 862
@@ -974,11 +908,11 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> {
974 } 908 }
975 909
976 pub fn check_any(&self, irqs: u8) -> bool { 910 pub fn check_any(&self, irqs: u8) -> bool {
977 unsafe { PIO::PIO.irq().read().irq() & irqs != 0 } 911 PIO::PIO.irq().read().irq() & irqs != 0
978 } 912 }
979 913
980 pub fn check_all(&self, irqs: u8) -> bool { 914 pub fn check_all(&self, irqs: u8) -> bool {
981 unsafe { PIO::PIO.irq().read().irq() & irqs == irqs } 915 PIO::PIO.irq().read().irq() & irqs == irqs
982 } 916 }
983 917
984 pub fn clear(&self, irq_no: usize) { 918 pub fn clear(&self, irq_no: usize) {
@@ -987,7 +921,7 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> {
987 } 921 }
988 922
989 pub fn clear_all(&self, irqs: u8) { 923 pub fn clear_all(&self, irqs: u8) {
990 unsafe { PIO::PIO.irq().write(|w| w.set_irq(irqs)) } 924 PIO::PIO.irq().write(|w| w.set_irq(irqs))
991 } 925 }
992 926
993 pub fn set(&self, irq_no: usize) { 927 pub fn set(&self, irq_no: usize) {
@@ -996,7 +930,7 @@ impl<'d, PIO: Instance> IrqFlags<'d, PIO> {
996 } 930 }
997 931
998 pub fn set_all(&self, irqs: u8) { 932 pub fn set_all(&self, irqs: u8) {
999 unsafe { PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs)) } 933 PIO::PIO.irq_force().write(|w| w.set_irq_force(irqs))
1000 } 934 }
1001} 935}
1002 936
@@ -1068,9 +1002,7 @@ fn on_pio_drop<PIO: Instance>() {
1068 // we only have 30 pins. don't test the other two since gpio() asserts. 1002 // we only have 30 pins. don't test the other two since gpio() asserts.
1069 for i in 0..30 { 1003 for i in 0..30 {
1070 if used_pins & (1 << i) != 0 { 1004 if used_pins & (1 << i) != 0 {
1071 unsafe { 1005 pac::IO_BANK0.gpio(i).ctrl().write(|w| w.set_funcsel(null));
1072 pac::IO_BANK0.gpio(i).ctrl().write(|w| w.set_funcsel(null));
1073 }
1074 } 1006 }
1075 } 1007 }
1076 } 1008 }
diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs
index 0f9dcf479..20bb88446 100644
--- a/embassy-rp/src/pwm.rs
+++ b/embassy-rp/src/pwm.rs
@@ -71,20 +71,18 @@ impl<'d, T: Channel> Pwm<'d, T> {
71 into_ref!(inner); 71 into_ref!(inner);
72 72
73 let p = inner.regs(); 73 let p = inner.regs();
74 unsafe { 74 p.csr().modify(|w| {
75 p.csr().modify(|w| { 75 w.set_divmode(divmode);
76 w.set_divmode(divmode); 76 w.set_en(false);
77 w.set_en(false); 77 });
78 }); 78 p.ctr().write(|w| w.0 = 0);
79 p.ctr().write(|w| w.0 = 0); 79 Self::configure(p, &config);
80 Self::configure(p, &config); 80
81 81 if let Some(pin) = &a {
82 if let Some(pin) = &a { 82 pin.io().ctrl().write(|w| w.set_funcsel(4));
83 pin.io().ctrl().write(|w| w.set_funcsel(4)); 83 }
84 } 84 if let Some(pin) = &b {
85 if let Some(pin) = &b { 85 pin.io().ctrl().write(|w| w.set_funcsel(4));
86 pin.io().ctrl().write(|w| w.set_funcsel(4));
87 }
88 } 86 }
89 Self { 87 Self {
90 inner, 88 inner,
@@ -161,31 +159,29 @@ impl<'d, T: Channel> Pwm<'d, T> {
161 panic!("Requested divider is too large"); 159 panic!("Requested divider is too large");
162 } 160 }
163 161
164 unsafe { 162 p.div().write_value(ChDiv(config.divider.to_bits() as u32));
165 p.div().write_value(ChDiv(config.divider.to_bits() as u32)); 163 p.cc().write(|w| {
166 p.cc().write(|w| { 164 w.set_a(config.compare_a);
167 w.set_a(config.compare_a); 165 w.set_b(config.compare_b);
168 w.set_b(config.compare_b); 166 });
169 }); 167 p.top().write(|w| w.set_top(config.top));
170 p.top().write(|w| w.set_top(config.top)); 168 p.csr().modify(|w| {
171 p.csr().modify(|w| { 169 w.set_a_inv(config.invert_a);
172 w.set_a_inv(config.invert_a); 170 w.set_b_inv(config.invert_b);
173 w.set_b_inv(config.invert_b); 171 w.set_ph_correct(config.phase_correct);
174 w.set_ph_correct(config.phase_correct); 172 w.set_en(config.enable);
175 w.set_en(config.enable); 173 });
176 });
177 }
178 } 174 }
179 175
180 #[inline] 176 #[inline]
181 pub unsafe fn phase_advance(&mut self) { 177 pub fn phase_advance(&mut self) {
182 let p = self.inner.regs(); 178 let p = self.inner.regs();
183 p.csr().write_set(|w| w.set_ph_adv(true)); 179 p.csr().write_set(|w| w.set_ph_adv(true));
184 while p.csr().read().ph_adv() {} 180 while p.csr().read().ph_adv() {}
185 } 181 }
186 182
187 #[inline] 183 #[inline]
188 pub unsafe fn phase_retard(&mut self) { 184 pub fn phase_retard(&mut self) {
189 let p = self.inner.regs(); 185 let p = self.inner.regs();
190 p.csr().write_set(|w| w.set_ph_ret(true)); 186 p.csr().write_set(|w| w.set_ph_ret(true));
191 while p.csr().read().ph_ret() {} 187 while p.csr().read().ph_ret() {}
@@ -193,12 +189,12 @@ impl<'d, T: Channel> Pwm<'d, T> {
193 189
194 #[inline] 190 #[inline]
195 pub fn counter(&self) -> u16 { 191 pub fn counter(&self) -> u16 {
196 unsafe { self.inner.regs().ctr().read().ctr() } 192 self.inner.regs().ctr().read().ctr()
197 } 193 }
198 194
199 #[inline] 195 #[inline]
200 pub fn set_counter(&self, ctr: u16) { 196 pub fn set_counter(&self, ctr: u16) {
201 unsafe { self.inner.regs().ctr().write(|w| w.set_ctr(ctr)) } 197 self.inner.regs().ctr().write(|w| w.set_ctr(ctr))
202 } 198 }
203 199
204 #[inline] 200 #[inline]
@@ -209,14 +205,12 @@ impl<'d, T: Channel> Pwm<'d, T> {
209 205
210 #[inline] 206 #[inline]
211 pub fn wrapped(&mut self) -> bool { 207 pub fn wrapped(&mut self) -> bool {
212 unsafe { pac::PWM.intr().read().0 & self.bit() != 0 } 208 pac::PWM.intr().read().0 & self.bit() != 0
213 } 209 }
214 210
215 #[inline] 211 #[inline]
216 pub fn clear_wrapped(&mut self) { 212 pub fn clear_wrapped(&mut self) {
217 unsafe { 213 pac::PWM.intr().write_value(Intr(self.bit() as _));
218 pac::PWM.intr().write_value(Intr(self.bit() as _));
219 }
220 } 214 }
221 215
222 #[inline] 216 #[inline]
@@ -237,26 +231,22 @@ impl PwmBatch {
237 pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) { 231 pub fn set_enabled(enabled: bool, batch: impl FnOnce(&mut PwmBatch)) {
238 let mut en = PwmBatch(0); 232 let mut en = PwmBatch(0);
239 batch(&mut en); 233 batch(&mut en);
240 unsafe { 234 if enabled {
241 if enabled { 235 pac::PWM.en().write_set(|w| w.0 = en.0);
242 pac::PWM.en().write_set(|w| w.0 = en.0); 236 } else {
243 } else { 237 pac::PWM.en().write_clear(|w| w.0 = en.0);
244 pac::PWM.en().write_clear(|w| w.0 = en.0);
245 }
246 } 238 }
247 } 239 }
248} 240}
249 241
250impl<'d, T: Channel> Drop for Pwm<'d, T> { 242impl<'d, T: Channel> Drop for Pwm<'d, T> {
251 fn drop(&mut self) { 243 fn drop(&mut self) {
252 unsafe { 244 self.inner.regs().csr().write_clear(|w| w.set_en(false));
253 self.inner.regs().csr().write_clear(|w| w.set_en(false)); 245 if let Some(pin) = &self.pin_a {
254 if let Some(pin) = &self.pin_a { 246 pin.io().ctrl().write(|w| w.set_funcsel(31));
255 pin.io().ctrl().write(|w| w.set_funcsel(31)); 247 }
256 } 248 if let Some(pin) = &self.pin_b {
257 if let Some(pin) = &self.pin_b { 249 pin.io().ctrl().write(|w| w.set_funcsel(31));
258 pin.io().ctrl().write(|w| w.set_funcsel(31));
259 }
260 } 250 }
261 } 251 }
262} 252}
diff --git a/embassy-rp/src/reset.rs b/embassy-rp/src/reset.rs
index edd47c223..70512fa14 100644
--- a/embassy-rp/src/reset.rs
+++ b/embassy-rp/src/reset.rs
@@ -4,11 +4,11 @@ use crate::pac;
4 4
5pub const ALL_PERIPHERALS: Peripherals = Peripherals(0x01ffffff); 5pub const ALL_PERIPHERALS: Peripherals = Peripherals(0x01ffffff);
6 6
7pub unsafe fn reset(peris: Peripherals) { 7pub(crate) fn reset(peris: Peripherals) {
8 pac::RESETS.reset().write_value(peris); 8 pac::RESETS.reset().write_value(peris);
9} 9}
10 10
11pub unsafe fn unreset_wait(peris: Peripherals) { 11pub(crate) fn unreset_wait(peris: Peripherals) {
12 // TODO use the "atomic clear" register version 12 // TODO use the "atomic clear" register version
13 pac::RESETS.reset().modify(|v| *v = Peripherals(v.0 & !peris.0)); 13 pac::RESETS.reset().modify(|v| *v = Peripherals(v.0 & !peris.0));
14 while ((!pac::RESETS.reset_done().read().0) & peris.0) != 0 {} 14 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 e1d886d4a..b18f12fc4 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> {
26 into_ref!(inner); 26 into_ref!(inner);
27 27
28 // Set the RTC divider 28 // Set the RTC divider
29 unsafe { inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1)) }; 29 inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1));
30 30
31 let mut result = Self { inner }; 31 let mut result = Self { inner };
32 result.set_leap_year_check(true); // should be on by default, make sure this is the case. 32 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> {
38 /// 38 ///
39 /// Leap year checking is enabled by default. 39 /// Leap year checking is enabled by default.
40 pub fn set_leap_year_check(&mut self, leap_year_check_enabled: bool) { 40 pub fn set_leap_year_check(&mut self, leap_year_check_enabled: bool) {
41 unsafe { 41 self.inner.regs().ctrl().modify(|w| {
42 self.inner 42 w.set_force_notleapyear(!leap_year_check_enabled);
43 .regs() 43 });
44 .ctrl()
45 .modify(|w| w.set_force_notleapyear(!leap_year_check_enabled))
46 };
47 } 44 }
48 45
49 /// Checks to see if this RealTimeClock is running 46 /// Checks to see if this RealTimeClock is running
50 pub fn is_running(&self) -> bool { 47 pub fn is_running(&self) -> bool {
51 unsafe { self.inner.regs().ctrl().read().rtc_active() } 48 self.inner.regs().ctrl().read().rtc_active()
52 } 49 }
53 50
54 /// Set the datetime to a new value. 51 /// Set the datetime to a new value.
@@ -60,25 +57,23 @@ impl<'d, T: Instance> RealTimeClock<'d, T> {
60 self::datetime::validate_datetime(&t).map_err(RtcError::InvalidDateTime)?; 57 self::datetime::validate_datetime(&t).map_err(RtcError::InvalidDateTime)?;
61 58
62 // disable RTC while we configure it 59 // disable RTC while we configure it
63 unsafe { 60 self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false));
64 self.inner.regs().ctrl().modify(|w| w.set_rtc_enable(false)); 61 while self.inner.regs().ctrl().read().rtc_active() {
65 while self.inner.regs().ctrl().read().rtc_active() { 62 core::hint::spin_loop();
66 core::hint::spin_loop(); 63 }
67 } 64
68 65 self.inner.regs().setup_0().write(|w| {
69 self.inner.regs().setup_0().write(|w| { 66 self::datetime::write_setup_0(&t, w);
70 self::datetime::write_setup_0(&t, w); 67 });
71 }); 68 self.inner.regs().setup_1().write(|w| {
72 self.inner.regs().setup_1().write(|w| { 69 self::datetime::write_setup_1(&t, w);
73 self::datetime::write_setup_1(&t, w); 70 });
74 }); 71
75 72 // Load the new datetime and re-enable RTC
76 // Load the new datetime and re-enable RTC 73 self.inner.regs().ctrl().write(|w| w.set_load(true));
77 self.inner.regs().ctrl().write(|w| w.set_load(true)); 74 self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true));
78 self.inner.regs().ctrl().write(|w| w.set_rtc_enable(true)); 75 while !self.inner.regs().ctrl().read().rtc_active() {
79 while !self.inner.regs().ctrl().read().rtc_active() { 76 core::hint::spin_loop();
80 core::hint::spin_loop();
81 }
82 } 77 }
83 Ok(()) 78 Ok(())
84 } 79 }
@@ -93,8 +88,8 @@ impl<'d, T: Instance> RealTimeClock<'d, T> {
93 return Err(RtcError::NotRunning); 88 return Err(RtcError::NotRunning);
94 } 89 }
95 90
96 let rtc_0 = unsafe { self.inner.regs().rtc_0().read() }; 91 let rtc_0 = self.inner.regs().rtc_0().read();
97 let rtc_1 = unsafe { self.inner.regs().rtc_1().read() }; 92 let rtc_1 = self.inner.regs().rtc_1().read();
98 93
99 self::datetime::datetime_from_registers(rtc_0, rtc_1).map_err(RtcError::InvalidDateTime) 94 self::datetime::datetime_from_registers(rtc_0, rtc_1).map_err(RtcError::InvalidDateTime)
100 } 95 }
@@ -103,12 +98,10 @@ impl<'d, T: Instance> RealTimeClock<'d, T> {
103 /// 98 ///
104 /// [`schedule_alarm`]: #method.schedule_alarm 99 /// [`schedule_alarm`]: #method.schedule_alarm
105 pub fn disable_alarm(&mut self) { 100 pub fn disable_alarm(&mut self) {
106 unsafe { 101 self.inner.regs().irq_setup_0().modify(|s| s.set_match_ena(false));
107 self.inner.regs().irq_setup_0().modify(|s| s.set_match_ena(false));
108 102
109 while self.inner.regs().irq_setup_0().read().match_active() { 103 while self.inner.regs().irq_setup_0().read().match_active() {
110 core::hint::spin_loop(); 104 core::hint::spin_loop();
111 }
112 } 105 }
113 } 106 }
114 107
@@ -132,21 +125,19 @@ impl<'d, T: Instance> RealTimeClock<'d, T> {
132 pub fn schedule_alarm(&mut self, filter: DateTimeFilter) { 125 pub fn schedule_alarm(&mut self, filter: DateTimeFilter) {
133 self.disable_alarm(); 126 self.disable_alarm();
134 127
135 unsafe { 128 self.inner.regs().irq_setup_0().write(|w| {
136 self.inner.regs().irq_setup_0().write(|w| { 129 filter.write_setup_0(w);
137 filter.write_setup_0(w); 130 });
138 }); 131 self.inner.regs().irq_setup_1().write(|w| {
139 self.inner.regs().irq_setup_1().write(|w| { 132 filter.write_setup_1(w);
140 filter.write_setup_1(w); 133 });
141 }); 134
142 135 self.inner.regs().inte().modify(|w| w.set_rtc(true));
143 self.inner.regs().inte().modify(|w| w.set_rtc(true)); 136
144 137 // Set the enable bit and check if it is set
145 // Set the enable bit and check if it is set 138 self.inner.regs().irq_setup_0().modify(|w| w.set_match_ena(true));
146 self.inner.regs().irq_setup_0().modify(|w| w.set_match_ena(true)); 139 while !self.inner.regs().irq_setup_0().read().match_active() {
147 while !self.inner.regs().irq_setup_0().read().match_active() { 140 core::hint::spin_loop();
148 core::hint::spin_loop();
149 }
150 } 141 }
151 } 142 }
152 143
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 7da214743..e817d074e 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> {
79 ) -> Self { 79 ) -> Self {
80 into_ref!(inner); 80 into_ref!(inner);
81 81
82 unsafe { 82 let p = inner.regs();
83 let p = inner.regs(); 83 let (presc, postdiv) = calc_prescs(config.frequency);
84 let (presc, postdiv) = calc_prescs(config.frequency); 84
85 85 p.cpsr().write(|w| w.set_cpsdvsr(presc));
86 p.cpsr().write(|w| w.set_cpsdvsr(presc)); 86 p.cr0().write(|w| {
87 p.cr0().write(|w| { 87 w.set_dss(0b0111); // 8bit
88 w.set_dss(0b0111); // 8bit 88 w.set_spo(config.polarity == Polarity::IdleHigh);
89 w.set_spo(config.polarity == Polarity::IdleHigh); 89 w.set_sph(config.phase == Phase::CaptureOnSecondTransition);
90 w.set_sph(config.phase == Phase::CaptureOnSecondTransition); 90 w.set_scr(postdiv);
91 w.set_scr(postdiv); 91 });
92 }); 92
93 93 // Always enable DREQ signals -- harmless if DMA is not listening
94 // Always enable DREQ signals -- harmless if DMA is not listening 94 p.dmacr().write(|reg| {
95 p.dmacr().write(|reg| { 95 reg.set_rxdmae(true);
96 reg.set_rxdmae(true); 96 reg.set_txdmae(true);
97 reg.set_txdmae(true); 97 });
98 }); 98
99 99 // finally, enable.
100 // finally, enable. 100 p.cr1().write(|w| w.set_sse(true));
101 p.cr1().write(|w| w.set_sse(true)); 101
102 102 if let Some(pin) = &clk {
103 if let Some(pin) = &clk { 103 pin.io().ctrl().write(|w| w.set_funcsel(1));
104 pin.io().ctrl().write(|w| w.set_funcsel(1)); 104 }
105 } 105 if let Some(pin) = &mosi {
106 if let Some(pin) = &mosi { 106 pin.io().ctrl().write(|w| w.set_funcsel(1));
107 pin.io().ctrl().write(|w| w.set_funcsel(1)); 107 }
108 } 108 if let Some(pin) = &miso {
109 if let Some(pin) = &miso { 109 pin.io().ctrl().write(|w| w.set_funcsel(1));
110 pin.io().ctrl().write(|w| w.set_funcsel(1)); 110 }
111 } 111 if let Some(pin) = &cs {
112 if let Some(pin) = &cs { 112 pin.io().ctrl().write(|w| w.set_funcsel(1));
113 pin.io().ctrl().write(|w| w.set_funcsel(1));
114 }
115 } 113 }
116 Self { 114 Self {
117 inner, 115 inner,
@@ -122,60 +120,52 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
122 } 120 }
123 121
124 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> { 122 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> {
125 unsafe { 123 let p = self.inner.regs();
126 let p = self.inner.regs(); 124 for &b in data {
127 for &b in data { 125 while !p.sr().read().tnf() {}
128 while !p.sr().read().tnf() {} 126 p.dr().write(|w| w.set_data(b as _));
129 p.dr().write(|w| w.set_data(b as _)); 127 while !p.sr().read().rne() {}
130 while !p.sr().read().rne() {} 128 let _ = p.dr().read();
131 let _ = p.dr().read();
132 }
133 } 129 }
134 self.flush()?; 130 self.flush()?;
135 Ok(()) 131 Ok(())
136 } 132 }
137 133
138 pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> { 134 pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> {
139 unsafe { 135 let p = self.inner.regs();
140 let p = self.inner.regs(); 136 for b in data {
141 for b in data { 137 while !p.sr().read().tnf() {}
142 while !p.sr().read().tnf() {} 138 p.dr().write(|w| w.set_data(*b as _));
143 p.dr().write(|w| w.set_data(*b as _)); 139 while !p.sr().read().rne() {}
144 while !p.sr().read().rne() {} 140 *b = p.dr().read().data() as u8;
145 *b = p.dr().read().data() as u8;
146 }
147 } 141 }
148 self.flush()?; 142 self.flush()?;
149 Ok(()) 143 Ok(())
150 } 144 }
151 145
152 pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> { 146 pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> {
153 unsafe { 147 let p = self.inner.regs();
154 let p = self.inner.regs(); 148 for b in data {
155 for b in data { 149 while !p.sr().read().tnf() {}
156 while !p.sr().read().tnf() {} 150 p.dr().write(|w| w.set_data(0));
157 p.dr().write(|w| w.set_data(0)); 151 while !p.sr().read().rne() {}
158 while !p.sr().read().rne() {} 152 *b = p.dr().read().data() as u8;
159 *b = p.dr().read().data() as u8;
160 }
161 } 153 }
162 self.flush()?; 154 self.flush()?;
163 Ok(()) 155 Ok(())
164 } 156 }
165 157
166 pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> { 158 pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
167 unsafe { 159 let p = self.inner.regs();
168 let p = self.inner.regs(); 160 let len = read.len().max(write.len());
169 let len = read.len().max(write.len()); 161 for i in 0..len {
170 for i in 0..len { 162 let wb = write.get(i).copied().unwrap_or(0);
171 let wb = write.get(i).copied().unwrap_or(0); 163 while !p.sr().read().tnf() {}
172 while !p.sr().read().tnf() {} 164 p.dr().write(|w| w.set_data(wb as _));
173 p.dr().write(|w| w.set_data(wb as _)); 165 while !p.sr().read().rne() {}
174 while !p.sr().read().rne() {} 166 let rb = p.dr().read().data() as u8;
175 let rb = p.dr().read().data() as u8; 167 if let Some(r) = read.get_mut(i) {
176 if let Some(r) = read.get_mut(i) { 168 *r = rb;
177 *r = rb;
178 }
179 } 169 }
180 } 170 }
181 self.flush()?; 171 self.flush()?;
@@ -183,29 +173,25 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
183 } 173 }
184 174
185 pub fn flush(&mut self) -> Result<(), Error> { 175 pub fn flush(&mut self) -> Result<(), Error> {
186 unsafe { 176 let p = self.inner.regs();
187 let p = self.inner.regs(); 177 while p.sr().read().bsy() {}
188 while p.sr().read().bsy() {}
189 }
190 Ok(()) 178 Ok(())
191 } 179 }
192 180
193 pub fn set_frequency(&mut self, freq: u32) { 181 pub fn set_frequency(&mut self, freq: u32) {
194 let (presc, postdiv) = calc_prescs(freq); 182 let (presc, postdiv) = calc_prescs(freq);
195 let p = self.inner.regs(); 183 let p = self.inner.regs();
196 unsafe { 184 // disable
197 // disable 185 p.cr1().write(|w| w.set_sse(false));
198 p.cr1().write(|w| w.set_sse(false)); 186
199 187 // change stuff
200 // change stuff 188 p.cpsr().write(|w| w.set_cpsdvsr(presc));
201 p.cpsr().write(|w| w.set_cpsdvsr(presc)); 189 p.cr0().modify(|w| {
202 p.cr0().modify(|w| { 190 w.set_scr(postdiv);
203 w.set_scr(postdiv); 191 });
204 }); 192
205 193 // enable
206 // enable 194 p.cr1().write(|w| w.set_sse(true));
207 p.cr1().write(|w| w.set_sse(true));
208 }
209 } 195 }
210} 196}
211 197
@@ -337,21 +323,19 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
337 let tx_transfer = unsafe { 323 let tx_transfer = unsafe {
338 // If we don't assign future to a variable, the data register pointer 324 // If we don't assign future to a variable, the data register pointer
339 // is held across an await and makes the future non-Send. 325 // is held across an await and makes the future non-Send.
340 crate::dma::write(tx_ch, buffer, self.inner.regs().dr().ptr() as *mut _, T::TX_DREQ) 326 crate::dma::write(tx_ch, buffer, self.inner.regs().dr().as_ptr() as *mut _, T::TX_DREQ)
341 }; 327 };
342 tx_transfer.await; 328 tx_transfer.await;
343 329
344 let p = self.inner.regs(); 330 let p = self.inner.regs();
345 unsafe { 331 while p.sr().read().bsy() {}
346 while p.sr().read().bsy() {}
347 332
348 // clear RX FIFO contents to prevent stale reads 333 // clear RX FIFO contents to prevent stale reads
349 while p.sr().read().rne() { 334 while p.sr().read().rne() {
350 let _: u16 = p.dr().read().data(); 335 let _: u16 = p.dr().read().data();
351 }
352 // clear RX overrun interrupt
353 p.icr().write(|w| w.set_roric(true));
354 } 336 }
337 // clear RX overrun interrupt
338 p.icr().write(|w| w.set_roric(true));
355 339
356 Ok(()) 340 Ok(())
357 } 341 }
@@ -363,14 +347,19 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
363 let rx_transfer = unsafe { 347 let rx_transfer = unsafe {
364 // If we don't assign future to a variable, the data register pointer 348 // If we don't assign future to a variable, the data register pointer
365 // is held across an await and makes the future non-Send. 349 // is held across an await and makes the future non-Send.
366 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, buffer, T::RX_DREQ) 350 crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, buffer, T::RX_DREQ)
367 }; 351 };
368 352
369 let tx_ch = self.tx_dma.as_mut().unwrap(); 353 let tx_ch = self.tx_dma.as_mut().unwrap();
370 let tx_transfer = unsafe { 354 let tx_transfer = unsafe {
371 // If we don't assign future to a variable, the data register pointer 355 // If we don't assign future to a variable, the data register pointer
372 // is held across an await and makes the future non-Send. 356 // is held across an await and makes the future non-Send.
373 crate::dma::write_repeated(tx_ch, self.inner.regs().dr().ptr() as *mut u8, buffer.len(), T::TX_DREQ) 357 crate::dma::write_repeated(
358 tx_ch,
359 self.inner.regs().dr().as_ptr() as *mut u8,
360 buffer.len(),
361 T::TX_DREQ,
362 )
374 }; 363 };
375 join(tx_transfer, rx_transfer).await; 364 join(tx_transfer, rx_transfer).await;
376 Ok(()) 365 Ok(())
@@ -394,7 +383,7 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
394 let rx_transfer = unsafe { 383 let rx_transfer = unsafe {
395 // If we don't assign future to a variable, the data register pointer 384 // If we don't assign future to a variable, the data register pointer
396 // is held across an await and makes the future non-Send. 385 // is held across an await and makes the future non-Send.
397 crate::dma::read(rx_ch, self.inner.regs().dr().ptr() as *const _, rx_ptr, T::RX_DREQ) 386 crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, rx_ptr, T::RX_DREQ)
398 }; 387 };
399 388
400 let mut tx_ch = self.tx_dma.as_mut().unwrap(); 389 let mut tx_ch = self.tx_dma.as_mut().unwrap();
@@ -403,13 +392,13 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
403 let tx_transfer = async { 392 let tx_transfer = async {
404 let p = self.inner.regs(); 393 let p = self.inner.regs();
405 unsafe { 394 unsafe {
406 crate::dma::write(&mut tx_ch, tx_ptr, p.dr().ptr() as *mut _, T::TX_DREQ).await; 395 crate::dma::write(&mut tx_ch, tx_ptr, p.dr().as_ptr() as *mut _, T::TX_DREQ).await;
407 396
408 if rx_len > tx_len { 397 if rx_len > tx_len {
409 let write_bytes_len = rx_len - tx_len; 398 let write_bytes_len = rx_len - tx_len;
410 // write dummy data 399 // write dummy data
411 // this will disable incrementation of the buffers 400 // this will disable incrementation of the buffers
412 crate::dma::write_repeated(tx_ch, p.dr().ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await 401 crate::dma::write_repeated(tx_ch, p.dr().as_ptr() as *mut u8, write_bytes_len, T::TX_DREQ).await
413 } 402 }
414 } 403 }
415 }; 404 };
@@ -418,16 +407,14 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
418 // if tx > rx we should clear any overflow of the FIFO SPI buffer 407 // if tx > rx we should clear any overflow of the FIFO SPI buffer
419 if tx_len > rx_len { 408 if tx_len > rx_len {
420 let p = self.inner.regs(); 409 let p = self.inner.regs();
421 unsafe { 410 while p.sr().read().bsy() {}
422 while p.sr().read().bsy() {}
423 411
424 // clear RX FIFO contents to prevent stale reads 412 // clear RX FIFO contents to prevent stale reads
425 while p.sr().read().rne() { 413 while p.sr().read().rne() {
426 let _: u16 = p.dr().read().data(); 414 let _: u16 = p.dr().read().data();
427 }
428 // clear RX overrun interrupt
429 p.icr().write(|w| w.set_roric(true));
430 } 415 }
416 // clear RX overrun interrupt
417 p.icr().write(|w| w.set_roric(true));
431 } 418 }
432 419
433 Ok(()) 420 Ok(())
@@ -625,14 +612,12 @@ impl<'d, T: Instance, M: Mode> SetConfig for Spi<'d, T, M> {
625 fn set_config(&mut self, config: &Self::Config) { 612 fn set_config(&mut self, config: &Self::Config) {
626 let p = self.inner.regs(); 613 let p = self.inner.regs();
627 let (presc, postdiv) = calc_prescs(config.frequency); 614 let (presc, postdiv) = calc_prescs(config.frequency);
628 unsafe { 615 p.cpsr().write(|w| w.set_cpsdvsr(presc));
629 p.cpsr().write(|w| w.set_cpsdvsr(presc)); 616 p.cr0().write(|w| {
630 p.cr0().write(|w| { 617 w.set_dss(0b0111); // 8bit
631 w.set_dss(0b0111); // 8bit 618 w.set_spo(config.polarity == Polarity::IdleHigh);
632 w.set_spo(config.polarity == Polarity::IdleHigh); 619 w.set_sph(config.phase == Phase::CaptureOnSecondTransition);
633 w.set_sph(config.phase == Phase::CaptureOnSecondTransition); 620 w.set_scr(postdiv);
634 w.set_scr(postdiv); 621 });
635 });
636 }
637 } 622 }
638} 623}
diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs
index ca8c96c0f..faa8df037 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{
34impl Driver for TimerDriver { 34impl Driver for TimerDriver {
35 fn now(&self) -> u64 { 35 fn now(&self) -> u64 {
36 loop { 36 loop {
37 unsafe { 37 let hi = pac::TIMER.timerawh().read();
38 let hi = pac::TIMER.timerawh().read(); 38 let lo = pac::TIMER.timerawl().read();
39 let lo = pac::TIMER.timerawl().read(); 39 let hi2 = pac::TIMER.timerawh().read();
40 let hi2 = pac::TIMER.timerawh().read(); 40 if hi == hi2 {
41 if hi == hi2 { 41 return (hi as u64) << 32 | (lo as u64);
42 return (hi as u64) << 32 | (lo as u64);
43 }
44 } 42 }
45 } 43 }
46 } 44 }
@@ -78,13 +76,13 @@ impl Driver for TimerDriver {
78 // Note that we're not checking the high bits at all. This means the irq may fire early 76 // Note that we're not checking the high bits at all. This means the irq may fire early
79 // if the alarm is more than 72 minutes (2^32 us) in the future. This is OK, since on irq fire 77 // if the alarm is more than 72 minutes (2^32 us) in the future. This is OK, since on irq fire
80 // it is checked if the alarm time has passed. 78 // it is checked if the alarm time has passed.
81 unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; 79 pac::TIMER.alarm(n).write_value(timestamp as u32);
82 80
83 let now = self.now(); 81 let now = self.now();
84 if timestamp <= now { 82 if timestamp <= now {
85 // If alarm timestamp has passed the alarm will not fire. 83 // If alarm timestamp has passed the alarm will not fire.
86 // Disarm the alarm and return `false` to indicate that. 84 // Disarm the alarm and return `false` to indicate that.
87 unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) } 85 pac::TIMER.armed().write(|w| w.set_armed(1 << n));
88 86
89 alarm.timestamp.set(u64::MAX); 87 alarm.timestamp.set(u64::MAX);
90 88
@@ -106,17 +104,17 @@ impl TimerDriver {
106 } else { 104 } else {
107 // Not elapsed, arm it again. 105 // Not elapsed, arm it again.
108 // This can happen if it was set more than 2^32 us in the future. 106 // This can happen if it was set more than 2^32 us in the future.
109 unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; 107 pac::TIMER.alarm(n).write_value(timestamp as u32);
110 } 108 }
111 }); 109 });
112 110
113 // clear the irq 111 // clear the irq
114 unsafe { pac::TIMER.intr().write(|w| w.set_alarm(n, true)) } 112 pac::TIMER.intr().write(|w| w.set_alarm(n, true));
115 } 113 }
116 114
117 fn trigger_alarm(&self, n: usize, cs: CriticalSection) { 115 fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
118 // disarm 116 // disarm
119 unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) } 117 pac::TIMER.armed().write(|w| w.set_armed(1 << n));
120 118
121 let alarm = &self.alarms.borrow(cs)[n]; 119 let alarm = &self.alarms.borrow(cs)[n];
122 alarm.timestamp.set(u64::MAX); 120 alarm.timestamp.set(u64::MAX);
@@ -153,24 +151,24 @@ pub unsafe fn init() {
153 151
154#[cfg(feature = "rt")] 152#[cfg(feature = "rt")]
155#[interrupt] 153#[interrupt]
156unsafe fn TIMER_IRQ_0() { 154fn TIMER_IRQ_0() {
157 DRIVER.check_alarm(0) 155 DRIVER.check_alarm(0)
158} 156}
159 157
160#[cfg(feature = "rt")] 158#[cfg(feature = "rt")]
161#[interrupt] 159#[interrupt]
162unsafe fn TIMER_IRQ_1() { 160fn TIMER_IRQ_1() {
163 DRIVER.check_alarm(1) 161 DRIVER.check_alarm(1)
164} 162}
165 163
166#[cfg(feature = "rt")] 164#[cfg(feature = "rt")]
167#[interrupt] 165#[interrupt]
168unsafe fn TIMER_IRQ_2() { 166fn TIMER_IRQ_2() {
169 DRIVER.check_alarm(2) 167 DRIVER.check_alarm(2)
170} 168}
171 169
172#[cfg(feature = "rt")] 170#[cfg(feature = "rt")]
173#[interrupt] 171#[interrupt]
174unsafe fn TIMER_IRQ_3() { 172fn TIMER_IRQ_3() {
175 DRIVER.check_alarm(3) 173 DRIVER.check_alarm(3)
176} 174}
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index 6660d5dc9..30eeb5476 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>(
73 // we clear it after it happens. The downside is that the we manually have 73 // we clear it after it happens. The downside is that the we manually have
74 // to pend the ISR when we want data transmission to start. 74 // to pend the ISR when we want data transmission to start.
75 let regs = T::regs(); 75 let regs = T::regs();
76 unsafe { 76 regs.uartimsc().write(|w| {
77 regs.uartimsc().write(|w| { 77 w.set_rxim(true);
78 w.set_rxim(true); 78 w.set_rtim(true);
79 w.set_rtim(true); 79 w.set_txim(true);
80 w.set_txim(true); 80 });
81 }); 81
82 82 T::Interrupt::unpend();
83 T::Interrupt::unpend(); 83 unsafe { T::Interrupt::enable() };
84 T::Interrupt::enable();
85 };
86} 84}
87 85
88impl<'d, T: Instance> BufferedUart<'d, T> { 86impl<'d, T: Instance> BufferedUart<'d, T> {
@@ -247,12 +245,10 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
247 // (Re-)Enable the interrupt to receive more data in case it was 245 // (Re-)Enable the interrupt to receive more data in case it was
248 // disabled because the buffer was full or errors were detected. 246 // disabled because the buffer was full or errors were detected.
249 let regs = T::regs(); 247 let regs = T::regs();
250 unsafe { 248 regs.uartimsc().write_set(|w| {
251 regs.uartimsc().write_set(|w| { 249 w.set_rxim(true);
252 w.set_rxim(true); 250 w.set_rtim(true);
253 w.set_rtim(true); 251 });
254 });
255 }
256 252
257 Poll::Ready(result) 253 Poll::Ready(result)
258 } 254 }
@@ -299,12 +295,10 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
299 // (Re-)Enable the interrupt to receive more data in case it was 295 // (Re-)Enable the interrupt to receive more data in case it was
300 // disabled because the buffer was full or errors were detected. 296 // disabled because the buffer was full or errors were detected.
301 let regs = T::regs(); 297 let regs = T::regs();
302 unsafe { 298 regs.uartimsc().write_set(|w| {
303 regs.uartimsc().write_set(|w| { 299 w.set_rxim(true);
304 w.set_rxim(true); 300 w.set_rtim(true);
305 w.set_rtim(true); 301 });
306 });
307 }
308 } 302 }
309} 303}
310 304
@@ -414,7 +408,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
414 } 408 }
415 409
416 pub fn busy(&self) -> bool { 410 pub fn busy(&self) -> bool {
417 unsafe { T::regs().uartfr().read().busy() } 411 T::regs().uartfr().read().busy()
418 } 412 }
419 413
420 /// Assert a break condition after waiting for the transmit buffers to empty, 414 /// Assert a break condition after waiting for the transmit buffers to empty,
@@ -426,42 +420,35 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
426 /// for the transmit fifo to empty, which may take a while on slow links. 420 /// for the transmit fifo to empty, which may take a while on slow links.
427 pub async fn send_break(&mut self, bits: u32) { 421 pub async fn send_break(&mut self, bits: u32) {
428 let regs = T::regs(); 422 let regs = T::regs();
429 let bits = bits.max(unsafe { 423 let bits = bits.max({
430 let lcr = regs.uartlcr_h().read(); 424 let lcr = regs.uartlcr_h().read();
431 let width = lcr.wlen() as u32 + 5; 425 let width = lcr.wlen() as u32 + 5;
432 let parity = lcr.pen() as u32; 426 let parity = lcr.pen() as u32;
433 let stops = 1 + lcr.stp2() as u32; 427 let stops = 1 + lcr.stp2() as u32;
434 2 * (1 + width + parity + stops) 428 2 * (1 + width + parity + stops)
435 }); 429 });
436 let divx64 = unsafe { 430 let divx64 = (((regs.uartibrd().read().baud_divint() as u32) << 6)
437 ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32 431 + regs.uartfbrd().read().baud_divfrac() as u32) as u64;
438 } as u64;
439 let div_clk = clk_peri_freq() as u64 * 64; 432 let div_clk = clk_peri_freq() as u64 * 64;
440 let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk; 433 let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk;
441 434
442 Self::flush().await.unwrap(); 435 Self::flush().await.unwrap();
443 while self.busy() {} 436 while self.busy() {}
444 unsafe { 437 regs.uartlcr_h().write_set(|w| w.set_brk(true));
445 regs.uartlcr_h().write_set(|w| w.set_brk(true));
446 }
447 Timer::after(Duration::from_micros(wait_usecs)).await; 438 Timer::after(Duration::from_micros(wait_usecs)).await;
448 unsafe { 439 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
449 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
450 }
451 } 440 }
452} 441}
453 442
454impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { 443impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
455 fn drop(&mut self) { 444 fn drop(&mut self) {
456 let state = T::buffered_state(); 445 let state = T::buffered_state();
457 unsafe { 446 unsafe { state.rx_buf.deinit() }
458 state.rx_buf.deinit();
459 447
460 // TX is inactive if the the buffer is not available. 448 // TX is inactive if the the buffer is not available.
461 // We can now unregister the interrupt handler 449 // We can now unregister the interrupt handler
462 if state.tx_buf.len() == 0 { 450 if state.tx_buf.len() == 0 {
463 T::Interrupt::disable(); 451 T::Interrupt::disable();
464 }
465 } 452 }
466 } 453 }
467} 454}
@@ -469,14 +456,12 @@ impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
469impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> { 456impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
470 fn drop(&mut self) { 457 fn drop(&mut self) {
471 let state = T::buffered_state(); 458 let state = T::buffered_state();
472 unsafe { 459 unsafe { state.tx_buf.deinit() }
473 state.tx_buf.deinit();
474 460
475 // RX is inactive if the the buffer is not available. 461 // RX is inactive if the the buffer is not available.
476 // We can now unregister the interrupt handler 462 // We can now unregister the interrupt handler
477 if state.rx_buf.len() == 0 { 463 if state.rx_buf.len() == 0 {
478 T::Interrupt::disable(); 464 T::Interrupt::disable();
479 }
480 } 465 }
481 } 466 }
482} 467}
@@ -494,94 +479,92 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for BufferedInterr
494 479
495 let s = T::buffered_state(); 480 let s = T::buffered_state();
496 481
497 unsafe { 482 // Clear TX and error interrupt flags
498 // Clear TX and error interrupt flags 483 // RX interrupt flags are cleared by reading from the FIFO.
499 // RX interrupt flags are cleared by reading from the FIFO. 484 let ris = r.uartris().read();
500 let ris = r.uartris().read(); 485 r.uarticr().write(|w| {
501 r.uarticr().write(|w| { 486 w.set_txic(ris.txris());
502 w.set_txic(ris.txris()); 487 w.set_feic(ris.feris());
503 w.set_feic(ris.feris()); 488 w.set_peic(ris.peris());
504 w.set_peic(ris.peris()); 489 w.set_beic(ris.beris());
505 w.set_beic(ris.beris()); 490 w.set_oeic(ris.oeris());
506 w.set_oeic(ris.oeris()); 491 });
507 });
508 492
509 trace!("on_interrupt ris={:#X}", ris.0); 493 trace!("on_interrupt ris={:#X}", ris.0);
510 494
511 // Errors 495 // Errors
512 if ris.feris() { 496 if ris.feris() {
513 warn!("Framing error"); 497 warn!("Framing error");
514 } 498 }
515 if ris.peris() { 499 if ris.peris() {
516 warn!("Parity error"); 500 warn!("Parity error");
517 } 501 }
518 if ris.beris() { 502 if ris.beris() {
519 warn!("Break error"); 503 warn!("Break error");
520 } 504 }
521 if ris.oeris() { 505 if ris.oeris() {
522 warn!("Overrun error"); 506 warn!("Overrun error");
523 } 507 }
524 508
525 // RX 509 // RX
526 let mut rx_writer = s.rx_buf.writer(); 510 let mut rx_writer = unsafe { s.rx_buf.writer() };
527 let rx_buf = rx_writer.push_slice(); 511 let rx_buf = rx_writer.push_slice();
528 let mut n_read = 0; 512 let mut n_read = 0;
529 let mut error = false; 513 let mut error = false;
530 for rx_byte in rx_buf { 514 for rx_byte in rx_buf {
531 if r.uartfr().read().rxfe() { 515 if r.uartfr().read().rxfe() {
532 break; 516 break;
533 }
534 let dr = r.uartdr().read();
535 if (dr.0 >> 8) != 0 {
536 s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed);
537 error = true;
538 // only fill the buffer with valid characters. the current character is fine
539 // if the error is an overrun, but if we add it to the buffer we'll report
540 // the overrun one character too late. drop it instead and pretend we were
541 // a bit slower at draining the rx fifo than we actually were.
542 // this is consistent with blocking uart error reporting.
543 break;
544 }
545 *rx_byte = dr.data();
546 n_read += 1;
547 }
548 if n_read > 0 {
549 rx_writer.push_done(n_read);
550 s.rx_waker.wake();
551 } else if error {
552 s.rx_waker.wake();
553 } 517 }
554 // Disable any further RX interrupts when the buffer becomes full or 518 let dr = r.uartdr().read();
555 // errors have occurred. This lets us buffer additional errors in the 519 if (dr.0 >> 8) != 0 {
556 // fifo without needing more error storage locations, and most applications 520 s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed);
557 // will want to do a full reset of their uart state anyway once an error 521 error = true;
558 // has happened. 522 // only fill the buffer with valid characters. the current character is fine
559 if s.rx_buf.is_full() || error { 523 // if the error is an overrun, but if we add it to the buffer we'll report
560 r.uartimsc().write_clear(|w| { 524 // the overrun one character too late. drop it instead and pretend we were
561 w.set_rxim(true); 525 // a bit slower at draining the rx fifo than we actually were.
562 w.set_rtim(true); 526 // this is consistent with blocking uart error reporting.
563 }); 527 break;
564 } 528 }
529 *rx_byte = dr.data();
530 n_read += 1;
531 }
532 if n_read > 0 {
533 rx_writer.push_done(n_read);
534 s.rx_waker.wake();
535 } else if error {
536 s.rx_waker.wake();
537 }
538 // Disable any further RX interrupts when the buffer becomes full or
539 // errors have occurred. This lets us buffer additional errors in the
540 // fifo without needing more error storage locations, and most applications
541 // will want to do a full reset of their uart state anyway once an error
542 // has happened.
543 if s.rx_buf.is_full() || error {
544 r.uartimsc().write_clear(|w| {
545 w.set_rxim(true);
546 w.set_rtim(true);
547 });
548 }
565 549
566 // TX 550 // TX
567 let mut tx_reader = s.tx_buf.reader(); 551 let mut tx_reader = unsafe { s.tx_buf.reader() };
568 let tx_buf = tx_reader.pop_slice(); 552 let tx_buf = tx_reader.pop_slice();
569 let mut n_written = 0; 553 let mut n_written = 0;
570 for tx_byte in tx_buf.iter_mut() { 554 for tx_byte in tx_buf.iter_mut() {
571 if r.uartfr().read().txff() { 555 if r.uartfr().read().txff() {
572 break; 556 break;
573 }
574 r.uartdr().write(|w| w.set_data(*tx_byte));
575 n_written += 1;
576 }
577 if n_written > 0 {
578 tx_reader.pop_done(n_written);
579 s.tx_waker.wake();
580 } 557 }
581 // The TX interrupt only triggers once when the FIFO threshold is 558 r.uartdr().write(|w| w.set_data(*tx_byte));
582 // crossed. No need to disable it when the buffer becomes empty 559 n_written += 1;
583 // as it does re-trigger anymore once we have cleared it. 560 }
561 if n_written > 0 {
562 tx_reader.pop_done(n_written);
563 s.tx_waker.wake();
584 } 564 }
565 // The TX interrupt only triggers once when the FIFO threshold is
566 // crossed. No need to disable it when the buffer becomes empty
567 // as it does re-trigger anymore once we have cleared it.
585 } 568 }
586} 569}
587 570
@@ -695,24 +678,22 @@ mod eh02 {
695 678
696 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { 679 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
697 let r = T::regs(); 680 let r = T::regs();
698 unsafe { 681 if r.uartfr().read().rxfe() {
699 if r.uartfr().read().rxfe() { 682 return Err(nb::Error::WouldBlock);
700 return Err(nb::Error::WouldBlock); 683 }
701 }
702 684
703 let dr = r.uartdr().read(); 685 let dr = r.uartdr().read();
704 686
705 if dr.oe() { 687 if dr.oe() {
706 Err(nb::Error::Other(Error::Overrun)) 688 Err(nb::Error::Other(Error::Overrun))
707 } else if dr.be() { 689 } else if dr.be() {
708 Err(nb::Error::Other(Error::Break)) 690 Err(nb::Error::Other(Error::Break))
709 } else if dr.pe() { 691 } else if dr.pe() {
710 Err(nb::Error::Other(Error::Parity)) 692 Err(nb::Error::Other(Error::Parity))
711 } else if dr.fe() { 693 } else if dr.fe() {
712 Err(nb::Error::Other(Error::Framing)) 694 Err(nb::Error::Other(Error::Framing))
713 } else { 695 } else {
714 Ok(dr.data()) 696 Ok(dr.data())
715 }
716 } 697 }
717 } 698 }
718 } 699 }
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 5e3ae8a25..7b94bce5e 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> {
146 146
147 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 147 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
148 let r = T::regs(); 148 let r = T::regs();
149 unsafe { 149 for &b in buffer {
150 for &b in buffer { 150 while r.uartfr().read().txff() {}
151 while r.uartfr().read().txff() {} 151 r.uartdr().write(|w| w.set_data(b));
152 r.uartdr().write(|w| w.set_data(b));
153 }
154 } 152 }
155 Ok(()) 153 Ok(())
156 } 154 }
157 155
158 pub fn blocking_flush(&mut self) -> Result<(), Error> { 156 pub fn blocking_flush(&mut self) -> Result<(), Error> {
159 let r = T::regs(); 157 let r = T::regs();
160 unsafe { while !r.uartfr().read().txfe() {} } 158 while !r.uartfr().read().txfe() {}
161 Ok(()) 159 Ok(())
162 } 160 }
163 161
164 pub fn busy(&self) -> bool { 162 pub fn busy(&self) -> bool {
165 unsafe { T::regs().uartfr().read().busy() } 163 T::regs().uartfr().read().busy()
166 } 164 }
167 165
168 /// Assert a break condition after waiting for the transmit buffers to empty, 166 /// 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> {
174 /// for the transmit fifo to empty, which may take a while on slow links. 172 /// for the transmit fifo to empty, which may take a while on slow links.
175 pub async fn send_break(&mut self, bits: u32) { 173 pub async fn send_break(&mut self, bits: u32) {
176 let regs = T::regs(); 174 let regs = T::regs();
177 let bits = bits.max(unsafe { 175 let bits = bits.max({
178 let lcr = regs.uartlcr_h().read(); 176 let lcr = regs.uartlcr_h().read();
179 let width = lcr.wlen() as u32 + 5; 177 let width = lcr.wlen() as u32 + 5;
180 let parity = lcr.pen() as u32; 178 let parity = lcr.pen() as u32;
181 let stops = 1 + lcr.stp2() as u32; 179 let stops = 1 + lcr.stp2() as u32;
182 2 * (1 + width + parity + stops) 180 2 * (1 + width + parity + stops)
183 }); 181 });
184 let divx64 = unsafe { 182 let divx64 = (((regs.uartibrd().read().baud_divint() as u32) << 6)
185 ((regs.uartibrd().read().baud_divint() as u32) << 6) + regs.uartfbrd().read().baud_divfrac() as u32 183 + regs.uartfbrd().read().baud_divfrac() as u32) as u64;
186 } as u64;
187 let div_clk = clk_peri_freq() as u64 * 64; 184 let div_clk = clk_peri_freq() as u64 * 64;
188 let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk; 185 let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk;
189 186
190 self.blocking_flush().unwrap(); 187 self.blocking_flush().unwrap();
191 while self.busy() {} 188 while self.busy() {}
192 unsafe { 189 regs.uartlcr_h().write_set(|w| w.set_brk(true));
193 regs.uartlcr_h().write_set(|w| w.set_brk(true));
194 }
195 Timer::after(Duration::from_micros(wait_usecs)).await; 190 Timer::after(Duration::from_micros(wait_usecs)).await;
196 unsafe { 191 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
197 regs.uartlcr_h().write_clear(|w| w.set_brk(true));
198 }
199 } 192 }
200} 193}
201 194
@@ -221,7 +214,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> {
221 }); 214 });
222 // If we don't assign future to a variable, the data register pointer 215 // If we don't assign future to a variable, the data register pointer
223 // is held across an await and makes the future non-Send. 216 // is held across an await and makes the future non-Send.
224 crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ) 217 crate::dma::write(ch, buffer, T::regs().uartdr().as_ptr() as *mut _, T::TX_DREQ)
225 }; 218 };
226 transfer.await; 219 transfer.await;
227 Ok(()) 220 Ok(())
@@ -246,7 +239,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
246 debug_assert_eq!(has_irq, rx_dma.is_some()); 239 debug_assert_eq!(has_irq, rx_dma.is_some());
247 if has_irq { 240 if has_irq {
248 // disable all error interrupts initially 241 // disable all error interrupts initially
249 unsafe { T::regs().uartimsc().write(|w| w.0 = 0) } 242 T::regs().uartimsc().write(|w| w.0 = 0);
250 T::Interrupt::unpend(); 243 T::Interrupt::unpend();
251 unsafe { T::Interrupt::enable() }; 244 unsafe { T::Interrupt::enable() };
252 } 245 }
@@ -267,11 +260,11 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
267 fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { 260 fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
268 let r = T::regs(); 261 let r = T::regs();
269 for (i, b) in buffer.iter_mut().enumerate() { 262 for (i, b) in buffer.iter_mut().enumerate() {
270 if unsafe { r.uartfr().read().rxfe() } { 263 if r.uartfr().read().rxfe() {
271 return Ok(i); 264 return Ok(i);
272 } 265 }
273 266
274 let dr = unsafe { r.uartdr().read() }; 267 let dr = r.uartdr().read();
275 268
276 if dr.oe() { 269 if dr.oe() {
277 return Err(Error::Overrun); 270 return Err(Error::Overrun);
@@ -292,15 +285,13 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
292impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> { 285impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
293 fn drop(&mut self) { 286 fn drop(&mut self) {
294 if let Some(_) = self.rx_dma { 287 if let Some(_) = self.rx_dma {
295 unsafe { 288 T::Interrupt::disable();
296 T::Interrupt::disable(); 289 // clear dma flags. irq handlers use these to disambiguate among themselves.
297 // clear dma flags. irq handlers use these to disambiguate among themselves. 290 T::regs().uartdmacr().write_clear(|reg| {
298 T::regs().uartdmacr().write_clear(|reg| { 291 reg.set_rxdmae(true);
299 reg.set_rxdmae(true); 292 reg.set_txdmae(true);
300 reg.set_txdmae(true); 293 reg.set_dmaonerr(true);
301 reg.set_dmaonerr(true); 294 });
302 });
303 }
304 } 295 }
305 } 296 }
306} 297}
@@ -355,14 +346,12 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
355 // clear error flags before we drain the fifo. errors that have accumulated 346 // clear error flags before we drain the fifo. errors that have accumulated
356 // in the flags will also be present in the fifo. 347 // in the flags will also be present in the fifo.
357 T::dma_state().rx_errs.store(0, Ordering::Relaxed); 348 T::dma_state().rx_errs.store(0, Ordering::Relaxed);
358 unsafe { 349 T::regs().uarticr().write(|w| {
359 T::regs().uarticr().write(|w| { 350 w.set_oeic(true);
360 w.set_oeic(true); 351 w.set_beic(true);
361 w.set_beic(true); 352 w.set_peic(true);
362 w.set_peic(true); 353 w.set_feic(true);
363 w.set_feic(true); 354 });
364 });
365 }
366 355
367 // then drain the fifo. we need to read at most 32 bytes. errors that apply 356 // then drain the fifo. we need to read at most 32 bytes. errors that apply
368 // to fifo bytes will be reported directly. 357 // to fifo bytes will be reported directly.
@@ -379,20 +368,20 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
379 // interrupt flags will have been raised, and those will be picked up immediately 368 // interrupt flags will have been raised, and those will be picked up immediately
380 // by the interrupt handler. 369 // by the interrupt handler.
381 let ch = self.rx_dma.as_mut().unwrap(); 370 let ch = self.rx_dma.as_mut().unwrap();
371 T::regs().uartimsc().write_set(|w| {
372 w.set_oeim(true);
373 w.set_beim(true);
374 w.set_peim(true);
375 w.set_feim(true);
376 });
377 T::regs().uartdmacr().write_set(|reg| {
378 reg.set_rxdmae(true);
379 reg.set_dmaonerr(true);
380 });
382 let transfer = unsafe { 381 let transfer = unsafe {
383 T::regs().uartimsc().write_set(|w| {
384 w.set_oeim(true);
385 w.set_beim(true);
386 w.set_peim(true);
387 w.set_feim(true);
388 });
389 T::regs().uartdmacr().write_set(|reg| {
390 reg.set_rxdmae(true);
391 reg.set_dmaonerr(true);
392 });
393 // If we don't assign future to a variable, the data register pointer 382 // If we don't assign future to a variable, the data register pointer
394 // is held across an await and makes the future non-Send. 383 // is held across an await and makes the future non-Send.
395 crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ) 384 crate::dma::read(ch, T::regs().uartdr().as_ptr() as *const _, buffer, T::RX_DREQ)
396 }; 385 };
397 386
398 // wait for either the transfer to complete or an error to happen. 387 // 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> {
575 config: Config, 564 config: Config,
576 ) { 565 ) {
577 let r = T::regs(); 566 let r = T::regs();
578 unsafe { 567 if let Some(pin) = &tx {
579 if let Some(pin) = &tx { 568 pin.io().ctrl().write(|w| {
580 pin.io().ctrl().write(|w| { 569 w.set_funcsel(2);
581 w.set_funcsel(2); 570 w.set_outover(if config.invert_tx {
582 w.set_outover(if config.invert_tx { 571 Outover::INVERT
583 Outover::INVERT 572 } else {
584 } else { 573 Outover::NORMAL
585 Outover::NORMAL
586 });
587 }); 574 });
588 pin.pad_ctrl().write(|w| w.set_ie(true)); 575 });
589 } 576 pin.pad_ctrl().write(|w| w.set_ie(true));
590 if let Some(pin) = &rx { 577 }
591 pin.io().ctrl().write(|w| { 578 if let Some(pin) = &rx {
592 w.set_funcsel(2); 579 pin.io().ctrl().write(|w| {
593 w.set_inover(if config.invert_rx { 580 w.set_funcsel(2);
594 Inover::INVERT 581 w.set_inover(if config.invert_rx {
595 } else { 582 Inover::INVERT
596 Inover::NORMAL 583 } else {
597 }); 584 Inover::NORMAL
598 }); 585 });
599 pin.pad_ctrl().write(|w| w.set_ie(true)); 586 });
600 } 587 pin.pad_ctrl().write(|w| w.set_ie(true));
601 if let Some(pin) = &cts { 588 }
602 pin.io().ctrl().write(|w| { 589 if let Some(pin) = &cts {
603 w.set_funcsel(2); 590 pin.io().ctrl().write(|w| {
604 w.set_inover(if config.invert_cts { 591 w.set_funcsel(2);
605 Inover::INVERT 592 w.set_inover(if config.invert_cts {
606 } else { 593 Inover::INVERT
607 Inover::NORMAL 594 } else {
608 }); 595 Inover::NORMAL
609 }); 596 });
610 pin.pad_ctrl().write(|w| w.set_ie(true)); 597 });
611 } 598 pin.pad_ctrl().write(|w| w.set_ie(true));
612 if let Some(pin) = &rts { 599 }
613 pin.io().ctrl().write(|w| { 600 if let Some(pin) = &rts {
614 w.set_funcsel(2); 601 pin.io().ctrl().write(|w| {
615 w.set_outover(if config.invert_rts { 602 w.set_funcsel(2);
616 Outover::INVERT 603 w.set_outover(if config.invert_rts {
617 } else { 604 Outover::INVERT
618 Outover::NORMAL 605 } else {
619 }); 606 Outover::NORMAL
620 }); 607 });
621 pin.pad_ctrl().write(|w| w.set_ie(true)); 608 });
622 } 609 pin.pad_ctrl().write(|w| w.set_ie(true));
610 }
623 611
624 Self::set_baudrate_inner(config.baudrate); 612 Self::set_baudrate_inner(config.baudrate);
625 613
626 let (pen, eps) = match config.parity { 614 let (pen, eps) = match config.parity {
627 Parity::ParityNone => (false, false), 615 Parity::ParityNone => (false, false),
628 Parity::ParityOdd => (true, false), 616 Parity::ParityOdd => (true, false),
629 Parity::ParityEven => (true, true), 617 Parity::ParityEven => (true, true),
630 }; 618 };
631 619
632 r.uartlcr_h().write(|w| { 620 r.uartlcr_h().write(|w| {
633 w.set_wlen(config.data_bits.bits()); 621 w.set_wlen(config.data_bits.bits());
634 w.set_stp2(config.stop_bits == StopBits::STOP2); 622 w.set_stp2(config.stop_bits == StopBits::STOP2);
635 w.set_pen(pen); 623 w.set_pen(pen);
636 w.set_eps(eps); 624 w.set_eps(eps);
637 w.set_fen(true); 625 w.set_fen(true);
638 }); 626 });
639 627
640 r.uartifls().write(|w| { 628 r.uartifls().write(|w| {
641 w.set_rxiflsel(0b000); 629 w.set_rxiflsel(0b000);
642 w.set_txiflsel(0b000); 630 w.set_txiflsel(0b000);
643 }); 631 });
644 632
645 r.uartcr().write(|w| { 633 r.uartcr().write(|w| {
646 w.set_uarten(true); 634 w.set_uarten(true);
647 w.set_rxe(true); 635 w.set_rxe(true);
648 w.set_txe(true); 636 w.set_txe(true);
649 w.set_ctsen(cts.is_some()); 637 w.set_ctsen(cts.is_some());
650 w.set_rtsen(rts.is_some()); 638 w.set_rtsen(rts.is_some());
651 }); 639 });
652 }
653 } 640 }
654 641
655 /// sets baudrate on runtime 642 /// sets baudrate on runtime
@@ -674,15 +661,13 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
674 baud_fbrd = 0; 661 baud_fbrd = 0;
675 } 662 }
676 663
677 unsafe { 664 // Load PL011's baud divisor registers
678 // Load PL011's baud divisor registers 665 r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd));
679 r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd)); 666 r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd));
680 r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd));
681 667
682 // PL011 needs a (dummy) line control register write to latch in the 668 // PL011 needs a (dummy) line control register write to latch in the
683 // divisors. We don't want to actually change LCR contents here. 669 // divisors. We don't want to actually change LCR contents here.
684 r.uartlcr_h().modify(|_| {}); 670 r.uartlcr_h().modify(|_| {});
685 }
686 } 671 }
687} 672}
688 673
@@ -731,24 +716,22 @@ mod eh02 {
731 type Error = Error; 716 type Error = Error;
732 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { 717 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
733 let r = T::regs(); 718 let r = T::regs();
734 unsafe { 719 if r.uartfr().read().rxfe() {
735 if r.uartfr().read().rxfe() { 720 return Err(nb::Error::WouldBlock);
736 return Err(nb::Error::WouldBlock); 721 }
737 }
738 722
739 let dr = r.uartdr().read(); 723 let dr = r.uartdr().read();
740 724
741 if dr.oe() { 725 if dr.oe() {
742 Err(nb::Error::Other(Error::Overrun)) 726 Err(nb::Error::Other(Error::Overrun))
743 } else if dr.be() { 727 } else if dr.be() {
744 Err(nb::Error::Other(Error::Break)) 728 Err(nb::Error::Other(Error::Break))
745 } else if dr.pe() { 729 } else if dr.pe() {
746 Err(nb::Error::Other(Error::Parity)) 730 Err(nb::Error::Other(Error::Parity))
747 } else if dr.fe() { 731 } else if dr.fe() {
748 Err(nb::Error::Other(Error::Framing)) 732 Err(nb::Error::Other(Error::Framing))
749 } else { 733 } else {
750 Ok(dr.data()) 734 Ok(dr.data())
751 }
752 } 735 }
753 } 736 }
754 } 737 }
@@ -758,22 +741,18 @@ mod eh02 {
758 741
759 fn write(&mut self, word: u8) -> Result<(), nb::Error<Self::Error>> { 742 fn write(&mut self, word: u8) -> Result<(), nb::Error<Self::Error>> {
760 let r = T::regs(); 743 let r = T::regs();
761 unsafe { 744 if r.uartfr().read().txff() {
762 if r.uartfr().read().txff() { 745 return Err(nb::Error::WouldBlock);
763 return Err(nb::Error::WouldBlock);
764 }
765
766 r.uartdr().write(|w| w.set_data(word));
767 } 746 }
747
748 r.uartdr().write(|w| w.set_data(word));
768 Ok(()) 749 Ok(())
769 } 750 }
770 751
771 fn flush(&mut self) -> Result<(), nb::Error<Self::Error>> { 752 fn flush(&mut self) -> Result<(), nb::Error<Self::Error>> {
772 let r = T::regs(); 753 let r = T::regs();
773 unsafe { 754 if !r.uartfr().read().txfe() {
774 if !r.uartfr().read().txfe() { 755 return Err(nb::Error::WouldBlock);
775 return Err(nb::Error::WouldBlock);
776 }
777 } 756 }
778 Ok(()) 757 Ok(())
779 } 758 }
@@ -854,22 +833,20 @@ mod eh1 {
854 impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> { 833 impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> {
855 fn read(&mut self) -> nb::Result<u8, Self::Error> { 834 fn read(&mut self) -> nb::Result<u8, Self::Error> {
856 let r = T::regs(); 835 let r = T::regs();
857 unsafe { 836 let dr = r.uartdr().read();
858 let dr = r.uartdr().read(); 837
859 838 if dr.oe() {
860 if dr.oe() { 839 Err(nb::Error::Other(Error::Overrun))
861 Err(nb::Error::Other(Error::Overrun)) 840 } else if dr.be() {
862 } else if dr.be() { 841 Err(nb::Error::Other(Error::Break))
863 Err(nb::Error::Other(Error::Break)) 842 } else if dr.pe() {
864 } else if dr.pe() { 843 Err(nb::Error::Other(Error::Parity))
865 Err(nb::Error::Other(Error::Parity)) 844 } else if dr.fe() {
866 } else if dr.fe() { 845 Err(nb::Error::Other(Error::Framing))
867 Err(nb::Error::Other(Error::Framing)) 846 } else if dr.fe() {
868 } else if dr.fe() { 847 Ok(dr.data())
869 Ok(dr.data()) 848 } else {
870 } else { 849 Err(nb::Error::WouldBlock)
871 Err(nb::Error::WouldBlock)
872 }
873 } 850 }
874 } 851 }
875 } 852 }
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs
index 9fb0dfb70..1900ab416 100644
--- a/embassy-rp/src/usb.rs
+++ b/embassy-rp/src/usb.rs
@@ -39,7 +39,7 @@ impl crate::usb::Instance for peripherals::USB {
39 39
40const EP_COUNT: usize = 16; 40const EP_COUNT: usize = 16;
41const EP_MEMORY_SIZE: usize = 4096; 41const EP_MEMORY_SIZE: usize = 4096;
42const EP_MEMORY: *mut u8 = pac::USBCTRL_DPRAM.0; 42const EP_MEMORY: *mut u8 = pac::USBCTRL_DPRAM.as_ptr() as *mut u8;
43 43
44const NEW_AW: AtomicWaker = AtomicWaker::new(); 44const NEW_AW: AtomicWaker = AtomicWaker::new();
45static BUS_WAKER: AtomicWaker = NEW_AW; 45static BUS_WAKER: AtomicWaker = NEW_AW;
@@ -111,7 +111,7 @@ impl<'d, T: Instance> Driver<'d, T> {
111 let regs = T::regs(); 111 let regs = T::regs();
112 unsafe { 112 unsafe {
113 // zero fill regs 113 // zero fill regs
114 let p = regs.0 as *mut u32; 114 let p = regs.as_ptr() as *mut u32;
115 for i in 0..0x9c / 4 { 115 for i in 0..0x9c / 4 {
116 p.add(i).write_volatile(0) 116 p.add(i).write_volatile(0)
117 } 117 }
@@ -121,20 +121,20 @@ impl<'d, T: Instance> Driver<'d, T> {
121 for i in 0..0x100 / 4 { 121 for i in 0..0x100 / 4 {
122 p.add(i).write_volatile(0) 122 p.add(i).write_volatile(0)
123 } 123 }
124
125 regs.usb_muxing().write(|w| {
126 w.set_to_phy(true);
127 w.set_softcon(true);
128 });
129 regs.usb_pwr().write(|w| {
130 w.set_vbus_detect(true);
131 w.set_vbus_detect_override_en(true);
132 });
133 regs.main_ctrl().write(|w| {
134 w.set_controller_en(true);
135 });
136 } 124 }
137 125
126 regs.usb_muxing().write(|w| {
127 w.set_to_phy(true);
128 w.set_softcon(true);
129 });
130 regs.usb_pwr().write(|w| {
131 w.set_vbus_detect(true);
132 w.set_vbus_detect_override_en(true);
133 });
134 regs.main_ctrl().write(|w| {
135 w.set_controller_en(true);
136 });
137
138 // Initialize the bus so that it signals that power is available 138 // Initialize the bus so that it signals that power is available
139 BUS_WAKER.wake(); 139 BUS_WAKER.wake();
140 140
@@ -213,22 +213,18 @@ impl<'d, T: Instance> Driver<'d, T> {
213 }; 213 };
214 214
215 match D::dir() { 215 match D::dir() {
216 Direction::Out => unsafe { 216 Direction::Out => T::dpram().ep_out_control(index - 1).write(|w| {
217 T::dpram().ep_out_control(index - 1).write(|w| { 217 w.set_enable(false);
218 w.set_enable(false); 218 w.set_buffer_address(addr);
219 w.set_buffer_address(addr); 219 w.set_interrupt_per_buff(true);
220 w.set_interrupt_per_buff(true); 220 w.set_endpoint_type(ep_type_reg);
221 w.set_endpoint_type(ep_type_reg); 221 }),
222 }) 222 Direction::In => T::dpram().ep_in_control(index - 1).write(|w| {
223 }, 223 w.set_enable(false);
224 Direction::In => unsafe { 224 w.set_buffer_address(addr);
225 T::dpram().ep_in_control(index - 1).write(|w| { 225 w.set_interrupt_per_buff(true);
226 w.set_enable(false); 226 w.set_endpoint_type(ep_type_reg);
227 w.set_buffer_address(addr); 227 }),
228 w.set_interrupt_per_buff(true);
229 w.set_endpoint_type(ep_type_reg);
230 })
231 },
232 } 228 }
233 229
234 Ok(Endpoint { 230 Ok(Endpoint {
@@ -315,22 +311,21 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
315 311
316 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) { 312 fn start(self, control_max_packet_size: u16) -> (Self::Bus, Self::ControlPipe) {
317 let regs = T::regs(); 313 let regs = T::regs();
318 unsafe { 314 regs.inte().write(|w| {
319 regs.inte().write(|w| { 315 w.set_bus_reset(true);
320 w.set_bus_reset(true); 316 w.set_buff_status(true);
321 w.set_buff_status(true); 317 w.set_dev_resume_from_host(true);
322 w.set_dev_resume_from_host(true); 318 w.set_dev_suspend(true);
323 w.set_dev_suspend(true); 319 w.set_setup_req(true);
324 w.set_setup_req(true); 320 });
325 }); 321 regs.int_ep_ctrl().write(|w| {
326 regs.int_ep_ctrl().write(|w| { 322 w.set_int_ep_active(0xFFFE); // all EPs
327 w.set_int_ep_active(0xFFFE); // all EPs 323 });
328 }); 324 regs.sie_ctrl().write(|w| {
329 regs.sie_ctrl().write(|w| { 325 w.set_ep0_int_1buf(true);
330 w.set_ep0_int_1buf(true); 326 w.set_pullup_en(true);
331 w.set_pullup_en(true); 327 });
332 }) 328
333 }
334 trace!("enabled"); 329 trace!("enabled");
335 330
336 ( 331 (
@@ -355,7 +350,7 @@ pub struct Bus<'d, T: Instance> {
355 350
356impl<'d, T: Instance> driver::Bus for Bus<'d, T> { 351impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
357 async fn poll(&mut self) -> Event { 352 async fn poll(&mut self) -> Event {
358 poll_fn(move |cx| unsafe { 353 poll_fn(move |cx| {
359 BUS_WAKER.register(cx.waker()); 354 BUS_WAKER.register(cx.waker());
360 355
361 if !self.inited { 356 if !self.inited {
@@ -425,14 +420,14 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> {
425 420
426 let n = ep_addr.index(); 421 let n = ep_addr.index();
427 match ep_addr.direction() { 422 match ep_addr.direction() {
428 Direction::In => unsafe { 423 Direction::In => {
429 T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled)); 424 T::dpram().ep_in_control(n - 1).modify(|w| w.set_enable(enabled));
430 T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| { 425 T::dpram().ep_in_buffer_control(ep_addr.index()).write(|w| {
431 w.set_pid(0, true); // first packet is DATA0, but PID is flipped before 426 w.set_pid(0, true); // first packet is DATA0, but PID is flipped before
432 }); 427 });
433 EP_IN_WAKERS[n].wake(); 428 EP_IN_WAKERS[n].wake();
434 }, 429 }
435 Direction::Out => unsafe { 430 Direction::Out => {
436 T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled)); 431 T::dpram().ep_out_control(n - 1).modify(|w| w.set_enable(enabled));
437 432
438 T::dpram().ep_out_buffer_control(ep_addr.index()).write(|w| { 433 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> {
446 w.set_available(0, true); 441 w.set_available(0, true);
447 }); 442 });
448 EP_OUT_WAKERS[n].wake(); 443 EP_OUT_WAKERS[n].wake();
449 }, 444 }
450 } 445 }
451 } 446 }
452 447
@@ -504,7 +499,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> {
504 let index = self.info.addr.index(); 499 let index = self.info.addr.index();
505 poll_fn(|cx| { 500 poll_fn(|cx| {
506 EP_IN_WAKERS[index].register(cx.waker()); 501 EP_IN_WAKERS[index].register(cx.waker());
507 let val = unsafe { T::dpram().ep_in_control(self.info.addr.index() - 1).read() }; 502 let val = T::dpram().ep_in_control(self.info.addr.index() - 1).read();
508 if val.enable() { 503 if val.enable() {
509 Poll::Ready(()) 504 Poll::Ready(())
510 } else { 505 } else {
@@ -526,7 +521,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, Out> {
526 let index = self.info.addr.index(); 521 let index = self.info.addr.index();
527 poll_fn(|cx| { 522 poll_fn(|cx| {
528 EP_OUT_WAKERS[index].register(cx.waker()); 523 EP_OUT_WAKERS[index].register(cx.waker());
529 let val = unsafe { T::dpram().ep_out_control(self.info.addr.index() - 1).read() }; 524 let val = T::dpram().ep_out_control(self.info.addr.index() - 1).read();
530 if val.enable() { 525 if val.enable() {
531 Poll::Ready(()) 526 Poll::Ready(())
532 } else { 527 } else {
@@ -542,7 +537,7 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
542 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> { 537 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, EndpointError> {
543 trace!("READ WAITING, buf.len() = {}", buf.len()); 538 trace!("READ WAITING, buf.len() = {}", buf.len());
544 let index = self.info.addr.index(); 539 let index = self.info.addr.index();
545 let val = poll_fn(|cx| unsafe { 540 let val = poll_fn(|cx| {
546 EP_OUT_WAKERS[index].register(cx.waker()); 541 EP_OUT_WAKERS[index].register(cx.waker());
547 let val = T::dpram().ep_out_buffer_control(index).read(); 542 let val = T::dpram().ep_out_buffer_control(index).read();
548 if val.available(0) { 543 if val.available(0) {
@@ -561,19 +556,17 @@ impl<'d, T: Instance> driver::EndpointOut for Endpoint<'d, T, Out> {
561 556
562 trace!("READ OK, rx_len = {}", rx_len); 557 trace!("READ OK, rx_len = {}", rx_len);
563 558
564 unsafe { 559 let pid = !val.pid(0);
565 let pid = !val.pid(0); 560 T::dpram().ep_out_buffer_control(index).write(|w| {
566 T::dpram().ep_out_buffer_control(index).write(|w| { 561 w.set_pid(0, pid);
567 w.set_pid(0, pid); 562 w.set_length(0, self.info.max_packet_size);
568 w.set_length(0, self.info.max_packet_size); 563 });
569 }); 564 cortex_m::asm::delay(12);
570 cortex_m::asm::delay(12); 565 T::dpram().ep_out_buffer_control(index).write(|w| {
571 T::dpram().ep_out_buffer_control(index).write(|w| { 566 w.set_pid(0, pid);
572 w.set_pid(0, pid); 567 w.set_length(0, self.info.max_packet_size);
573 w.set_length(0, self.info.max_packet_size); 568 w.set_available(0, true);
574 w.set_available(0, true); 569 });
575 });
576 }
577 570
578 Ok(rx_len) 571 Ok(rx_len)
579 } 572 }
@@ -588,7 +581,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
588 trace!("WRITE WAITING"); 581 trace!("WRITE WAITING");
589 582
590 let index = self.info.addr.index(); 583 let index = self.info.addr.index();
591 let val = poll_fn(|cx| unsafe { 584 let val = poll_fn(|cx| {
592 EP_IN_WAKERS[index].register(cx.waker()); 585 EP_IN_WAKERS[index].register(cx.waker());
593 let val = T::dpram().ep_in_buffer_control(index).read(); 586 let val = T::dpram().ep_in_buffer_control(index).read();
594 if val.available(0) { 587 if val.available(0) {
@@ -601,21 +594,19 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
601 594
602 self.buf.write(buf); 595 self.buf.write(buf);
603 596
604 unsafe { 597 let pid = !val.pid(0);
605 let pid = !val.pid(0); 598 T::dpram().ep_in_buffer_control(index).write(|w| {
606 T::dpram().ep_in_buffer_control(index).write(|w| { 599 w.set_pid(0, pid);
607 w.set_pid(0, pid); 600 w.set_length(0, buf.len() as _);
608 w.set_length(0, buf.len() as _); 601 w.set_full(0, true);
609 w.set_full(0, true); 602 });
610 }); 603 cortex_m::asm::delay(12);
611 cortex_m::asm::delay(12); 604 T::dpram().ep_in_buffer_control(index).write(|w| {
612 T::dpram().ep_in_buffer_control(index).write(|w| { 605 w.set_pid(0, pid);
613 w.set_pid(0, pid); 606 w.set_length(0, buf.len() as _);
614 w.set_length(0, buf.len() as _); 607 w.set_full(0, true);
615 w.set_full(0, true); 608 w.set_available(0, true);
616 w.set_available(0, true); 609 });
617 });
618 }
619 610
620 trace!("WRITE OK"); 611 trace!("WRITE OK");
621 612
@@ -637,9 +628,9 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
637 loop { 628 loop {
638 trace!("SETUP read waiting"); 629 trace!("SETUP read waiting");
639 let regs = T::regs(); 630 let regs = T::regs();
640 unsafe { regs.inte().write_set(|w| w.set_setup_req(true)) }; 631 regs.inte().write_set(|w| w.set_setup_req(true));
641 632
642 poll_fn(|cx| unsafe { 633 poll_fn(|cx| {
643 EP_OUT_WAKERS[0].register(cx.waker()); 634 EP_OUT_WAKERS[0].register(cx.waker());
644 let regs = T::regs(); 635 let regs = T::regs();
645 if regs.sie_status().read().setup_rec() { 636 if regs.sie_status().read().setup_rec() {
@@ -654,13 +645,11 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
654 EndpointBuffer::<T>::new(0, 8).read(&mut buf); 645 EndpointBuffer::<T>::new(0, 8).read(&mut buf);
655 646
656 let regs = T::regs(); 647 let regs = T::regs();
657 unsafe { 648 regs.sie_status().write(|w| w.set_setup_rec(true));
658 regs.sie_status().write(|w| w.set_setup_rec(true));
659 649
660 // set PID to 0, so (after toggling) first DATA is PID 1 650 // set PID to 0, so (after toggling) first DATA is PID 1
661 T::dpram().ep_in_buffer_control(0).write(|w| w.set_pid(0, false)); 651 T::dpram().ep_in_buffer_control(0).write(|w| w.set_pid(0, false));
662 T::dpram().ep_out_buffer_control(0).write(|w| w.set_pid(0, false)); 652 T::dpram().ep_out_buffer_control(0).write(|w| w.set_pid(0, false));
663 }
664 653
665 trace!("SETUP read ok"); 654 trace!("SETUP read ok");
666 return buf; 655 return buf;
@@ -668,23 +657,21 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
668 } 657 }
669 658
670 async fn data_out(&mut self, buf: &mut [u8], first: bool, last: bool) -> Result<usize, EndpointError> { 659 async fn data_out(&mut self, buf: &mut [u8], first: bool, last: bool) -> Result<usize, EndpointError> {
671 unsafe { 660 let bufcontrol = T::dpram().ep_out_buffer_control(0);
672 let bufcontrol = T::dpram().ep_out_buffer_control(0); 661 let pid = !bufcontrol.read().pid(0);
673 let pid = !bufcontrol.read().pid(0); 662 bufcontrol.write(|w| {
674 bufcontrol.write(|w| { 663 w.set_length(0, self.max_packet_size);
675 w.set_length(0, self.max_packet_size); 664 w.set_pid(0, pid);
676 w.set_pid(0, pid); 665 });
677 }); 666 cortex_m::asm::delay(12);
678 cortex_m::asm::delay(12); 667 bufcontrol.write(|w| {
679 bufcontrol.write(|w| { 668 w.set_length(0, self.max_packet_size);
680 w.set_length(0, self.max_packet_size); 669 w.set_pid(0, pid);
681 w.set_pid(0, pid); 670 w.set_available(0, true);
682 w.set_available(0, true); 671 });
683 });
684 }
685 672
686 trace!("control: data_out len={} first={} last={}", buf.len(), first, last); 673 trace!("control: data_out len={} first={} last={}", buf.len(), first, last);
687 let val = poll_fn(|cx| unsafe { 674 let val = poll_fn(|cx| {
688 EP_OUT_WAKERS[0].register(cx.waker()); 675 EP_OUT_WAKERS[0].register(cx.waker());
689 let val = T::dpram().ep_out_buffer_control(0).read(); 676 let val = T::dpram().ep_out_buffer_control(0).read();
690 if val.available(0) { 677 if val.available(0) {
@@ -714,24 +701,22 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
714 } 701 }
715 EndpointBuffer::<T>::new(0x100, 64).write(data); 702 EndpointBuffer::<T>::new(0x100, 64).write(data);
716 703
717 unsafe { 704 let bufcontrol = T::dpram().ep_in_buffer_control(0);
718 let bufcontrol = T::dpram().ep_in_buffer_control(0); 705 let pid = !bufcontrol.read().pid(0);
719 let pid = !bufcontrol.read().pid(0); 706 bufcontrol.write(|w| {
720 bufcontrol.write(|w| { 707 w.set_length(0, data.len() as _);
721 w.set_length(0, data.len() as _); 708 w.set_pid(0, pid);
722 w.set_pid(0, pid); 709 w.set_full(0, true);
723 w.set_full(0, true); 710 });
724 }); 711 cortex_m::asm::delay(12);
725 cortex_m::asm::delay(12); 712 bufcontrol.write(|w| {
726 bufcontrol.write(|w| { 713 w.set_length(0, data.len() as _);
727 w.set_length(0, data.len() as _); 714 w.set_pid(0, pid);
728 w.set_pid(0, pid); 715 w.set_full(0, true);
729 w.set_full(0, true); 716 w.set_available(0, true);
730 w.set_available(0, true); 717 });
731 });
732 }
733 718
734 poll_fn(|cx| unsafe { 719 poll_fn(|cx| {
735 EP_IN_WAKERS[0].register(cx.waker()); 720 EP_IN_WAKERS[0].register(cx.waker());
736 let bufcontrol = T::dpram().ep_in_buffer_control(0); 721 let bufcontrol = T::dpram().ep_in_buffer_control(0);
737 if bufcontrol.read().available(0) { 722 if bufcontrol.read().available(0) {
@@ -745,48 +730,44 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
745 730
746 if last { 731 if last {
747 // prepare status phase right away. 732 // prepare status phase right away.
748 unsafe { 733 let bufcontrol = T::dpram().ep_out_buffer_control(0);
749 let bufcontrol = T::dpram().ep_out_buffer_control(0);
750 bufcontrol.write(|w| {
751 w.set_length(0, 0);
752 w.set_pid(0, true);
753 });
754 cortex_m::asm::delay(12);
755 bufcontrol.write(|w| {
756 w.set_length(0, 0);
757 w.set_pid(0, true);
758 w.set_available(0, true);
759 });
760 }
761 }
762
763 Ok(())
764 }
765
766 async fn accept(&mut self) {
767 trace!("control: accept");
768
769 let bufcontrol = T::dpram().ep_in_buffer_control(0);
770 unsafe {
771 bufcontrol.write(|w| { 734 bufcontrol.write(|w| {
772 w.set_length(0, 0); 735 w.set_length(0, 0);
773 w.set_pid(0, true); 736 w.set_pid(0, true);
774 w.set_full(0, true);
775 }); 737 });
776 cortex_m::asm::delay(12); 738 cortex_m::asm::delay(12);
777 bufcontrol.write(|w| { 739 bufcontrol.write(|w| {
778 w.set_length(0, 0); 740 w.set_length(0, 0);
779 w.set_pid(0, true); 741 w.set_pid(0, true);
780 w.set_full(0, true);
781 w.set_available(0, true); 742 w.set_available(0, true);
782 }); 743 });
783 } 744 }
784 745
746 Ok(())
747 }
748
749 async fn accept(&mut self) {
750 trace!("control: accept");
751
752 let bufcontrol = T::dpram().ep_in_buffer_control(0);
753 bufcontrol.write(|w| {
754 w.set_length(0, 0);
755 w.set_pid(0, true);
756 w.set_full(0, true);
757 });
758 cortex_m::asm::delay(12);
759 bufcontrol.write(|w| {
760 w.set_length(0, 0);
761 w.set_pid(0, true);
762 w.set_full(0, true);
763 w.set_available(0, true);
764 });
765
785 // wait for completion before returning, needed so 766 // wait for completion before returning, needed so
786 // set_address() doesn't happen early. 767 // set_address() doesn't happen early.
787 poll_fn(|cx| { 768 poll_fn(|cx| {
788 EP_IN_WAKERS[0].register(cx.waker()); 769 EP_IN_WAKERS[0].register(cx.waker());
789 if unsafe { bufcontrol.read().available(0) } { 770 if bufcontrol.read().available(0) {
790 Poll::Pending 771 Poll::Pending
791 } else { 772 } else {
792 Poll::Ready(()) 773 Poll::Ready(())
@@ -799,14 +780,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
799 trace!("control: reject"); 780 trace!("control: reject");
800 781
801 let regs = T::regs(); 782 let regs = T::regs();
802 unsafe { 783 regs.ep_stall_arm().write_set(|w| {
803 regs.ep_stall_arm().write_set(|w| { 784 w.set_ep0_in(true);
804 w.set_ep0_in(true); 785 w.set_ep0_out(true);
805 w.set_ep0_out(true); 786 });
806 }); 787 T::dpram().ep_out_buffer_control(0).write(|w| w.set_stall(true));
807 T::dpram().ep_out_buffer_control(0).write(|w| w.set_stall(true)); 788 T::dpram().ep_in_buffer_control(0).write(|w| w.set_stall(true));
808 T::dpram().ep_in_buffer_control(0).write(|w| w.set_stall(true));
809 }
810 } 789 }
811 790
812 async fn accept_set_address(&mut self, addr: u8) { 791 async fn accept_set_address(&mut self, addr: u8) {
@@ -814,6 +793,6 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
814 793
815 let regs = T::regs(); 794 let regs = T::regs();
816 trace!("setting addr: {}", addr); 795 trace!("setting addr: {}", addr);
817 unsafe { regs.addr_endp().write(|w| w.set_address(addr)) } 796 regs.addr_endp().write(|w| w.set_address(addr))
818 } 797 }
819} 798}
diff --git a/embassy-rp/src/watchdog.rs b/embassy-rp/src/watchdog.rs
index 78a295ae7..d37795cc9 100644
--- a/embassy-rp/src/watchdog.rs
+++ b/embassy-rp/src/watchdog.rs
@@ -35,45 +35,37 @@ impl Watchdog {
35 /// * `cycles` - Total number of tick cycles before the next tick is generated. 35 /// * `cycles` - Total number of tick cycles before the next tick is generated.
36 /// It is expected to be the frequency in MHz of clk_ref. 36 /// It is expected to be the frequency in MHz of clk_ref.
37 pub fn enable_tick_generation(&mut self, cycles: u8) { 37 pub fn enable_tick_generation(&mut self, cycles: u8) {
38 unsafe { 38 let watchdog = pac::WATCHDOG;
39 let watchdog = pac::WATCHDOG; 39 watchdog.tick().write(|w| {
40 watchdog.tick().write(|w| { 40 w.set_enable(true);
41 w.set_enable(true); 41 w.set_cycles(cycles.into())
42 w.set_cycles(cycles.into()) 42 });
43 });
44 }
45 } 43 }
46 44
47 /// Defines whether or not the watchdog timer should be paused when processor(s) are in debug mode 45 /// Defines whether or not the watchdog timer should be paused when processor(s) are in debug mode
48 /// or when JTAG is accessing bus fabric 46 /// or when JTAG is accessing bus fabric
49 pub fn pause_on_debug(&mut self, pause: bool) { 47 pub fn pause_on_debug(&mut self, pause: bool) {
50 unsafe { 48 let watchdog = pac::WATCHDOG;
51 let watchdog = pac::WATCHDOG; 49 watchdog.ctrl().write(|w| {
52 watchdog.ctrl().write(|w| { 50 w.set_pause_dbg0(pause);
53 w.set_pause_dbg0(pause); 51 w.set_pause_dbg1(pause);
54 w.set_pause_dbg1(pause); 52 w.set_pause_jtag(pause);
55 w.set_pause_jtag(pause); 53 })
56 })
57 }
58 } 54 }
59 55
60 fn load_counter(&self, counter: u32) { 56 fn load_counter(&self, counter: u32) {
61 unsafe { 57 let watchdog = pac::WATCHDOG;
62 let watchdog = pac::WATCHDOG; 58 watchdog.load().write_value(pac::watchdog::regs::Load(counter));
63 watchdog.load().write_value(pac::watchdog::regs::Load(counter));
64 }
65 } 59 }
66 60
67 fn enable(&self, bit: bool) { 61 fn enable(&self, bit: bool) {
68 unsafe { 62 let watchdog = pac::WATCHDOG;
69 let watchdog = pac::WATCHDOG; 63 watchdog.ctrl().write(|w| w.set_enable(bit))
70 watchdog.ctrl().write(|w| w.set_enable(bit))
71 }
72 } 64 }
73 65
74 // Configure which hardware will be reset by the watchdog 66 // Configure which hardware will be reset by the watchdog
75 // (everything except ROSC, XOSC) 67 // (everything except ROSC, XOSC)
76 unsafe fn configure_wdog_reset_triggers(&self) { 68 fn configure_wdog_reset_triggers(&self) {
77 let psm = pac::PSM; 69 let psm = pac::PSM;
78 psm.wdsel().write_value(pac::psm::regs::Wdsel( 70 psm.wdsel().write_value(pac::psm::regs::Wdsel(
79 0x0001ffff & !(0x01 << 0usize) & !(0x01 << 1usize), 71 0x0001ffff & !(0x01 << 0usize) & !(0x01 << 1usize),
@@ -100,23 +92,19 @@ impl Watchdog {
100 self.load_value = delay_us * 2; 92 self.load_value = delay_us * 2;
101 93
102 self.enable(false); 94 self.enable(false);
103 unsafe { 95 self.configure_wdog_reset_triggers();
104 self.configure_wdog_reset_triggers();
105 }
106 self.load_counter(self.load_value); 96 self.load_counter(self.load_value);
107 self.enable(true); 97 self.enable(true);
108 } 98 }
109 99
110 /// Trigger a system reset 100 /// Trigger a system reset
111 pub fn trigger_reset(&mut self) { 101 pub fn trigger_reset(&mut self) {
112 unsafe { 102 self.configure_wdog_reset_triggers();
113 self.configure_wdog_reset_triggers(); 103 self.pause_on_debug(false);
114 self.pause_on_debug(false); 104 self.enable(true);
115 self.enable(true); 105 let watchdog = pac::WATCHDOG;
116 let watchdog = pac::WATCHDOG; 106 watchdog.ctrl().write(|w| {
117 watchdog.ctrl().write(|w| { 107 w.set_trigger(true);
118 w.set_trigger(true); 108 })
119 })
120 }
121 } 109 }
122} 110}
diff --git a/tests/rp/src/bin/float.rs b/tests/rp/src/bin/float.rs
index 6a982507a..0e0de85fa 100644
--- a/tests/rp/src/bin/float.rs
+++ b/tests/rp/src/bin/float.rs
@@ -18,11 +18,9 @@ async fn main(_spawner: Spawner) {
18 const PI_F: f32 = 3.1415926535f32; 18 const PI_F: f32 = 3.1415926535f32;
19 const PI_D: f64 = 3.14159265358979323846f64; 19 const PI_D: f64 = 3.14159265358979323846f64;
20 20
21 unsafe { 21 pac::BUSCTRL
22 pac::BUSCTRL 22 .perfsel(0)
23 .perfsel(0) 23 .write(|r| r.set_perfsel(pac::busctrl::vals::Perfsel::ROM));
24 .write(|r| r.set_perfsel(pac::busctrl::vals::Perfsel::ROM));
25 }
26 24
27 for i in 0..=360 { 25 for i in 0..=360 {
28 let rad_f = (i as f32) * PI_F / 180.0; 26 let rad_f = (i as f32) * PI_F / 180.0;
@@ -46,7 +44,7 @@ async fn main(_spawner: Spawner) {
46 Timer::after(Duration::from_millis(10)).await; 44 Timer::after(Duration::from_millis(10)).await;
47 } 45 }
48 46
49 let rom_accesses = unsafe { pac::BUSCTRL.perfctr(0).read().perfctr() }; 47 let rom_accesses = pac::BUSCTRL.perfctr(0).read().perfctr();
50 // every float operation used here uses at least 10 cycles 48 // every float operation used here uses at least 10 cycles
51 defmt::assert!(rom_accesses >= 360 * 12 * 10); 49 defmt::assert!(rom_accesses >= 360 * 12 * 10);
52 50