aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src
diff options
context:
space:
mode:
authorpennae <[email protected]>2023-07-28 18:45:57 +0200
committerpennae <[email protected]>2023-07-28 19:33:02 +0200
commitcbc8871a0bb40eb5fec82e7c27ed4c0127844c3c (patch)
tree333ab4bc2d1893d42529c6a378ea51c42f8c8d22 /embassy-rp/src
parentd752a3f9808ec9be64c720d3f80f152f0b7507df (diff)
rp: relocate programs implicitly during load
this removed the RelocatedProgram construction step from pio uses. there's not all that much to be said for the extra step because the origin can be set on the input program itself, and the remaining information exposed by RelocatedProgram can be exposed from LoadedProgram instead (even though it's already available on the pio_asm programs, albeit perhaps less convenient). we do lose access to the relocated instruction iterator, but we also cannot think of anything this iterator would actually be useful for outside of program loading.
Diffstat (limited to 'embassy-rp/src')
-rw-r--r--embassy-rp/src/lib.rs2
-rw-r--r--embassy-rp/src/pio.rs60
-rw-r--r--embassy-rp/src/relocate.rs5
3 files changed, 53 insertions, 14 deletions
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index ebec9fec6..45156458d 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -33,7 +33,7 @@ pub mod watchdog;
33// TODO: move `pio_instr_util` and `relocate` to inside `pio` 33// TODO: move `pio_instr_util` and `relocate` to inside `pio`
34pub mod pio; 34pub mod pio;
35pub mod pio_instr_util; 35pub mod pio_instr_util;
36pub mod relocate; 36pub(crate) mod relocate;
37 37
38// Reexports 38// Reexports
39pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 39pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs
index 464988b27..3de398af7 100644
--- a/embassy-rp/src/pio.rs
+++ b/embassy-rp/src/pio.rs
@@ -11,7 +11,7 @@ use fixed::types::extra::U8;
11use fixed::FixedU32; 11use fixed::FixedU32;
12use pac::io::vals::Gpio0ctrlFuncsel; 12use pac::io::vals::Gpio0ctrlFuncsel;
13use pac::pio::vals::SmExecctrlStatusSel; 13use pac::pio::vals::SmExecctrlStatusSel;
14use pio::{SideSet, Wrap}; 14use pio::{Program, SideSet, Wrap};
15 15
16use crate::dma::{Channel, Transfer, Word}; 16use crate::dma::{Channel, Transfer, Word};
17use crate::gpio::sealed::Pin as SealedPin; 17use crate::gpio::sealed::Pin as SealedPin;
@@ -734,23 +734,67 @@ pub struct InstanceMemory<'d, PIO: Instance> {
734 734
735pub struct LoadedProgram<'d, PIO: Instance> { 735pub struct LoadedProgram<'d, PIO: Instance> {
736 pub used_memory: InstanceMemory<'d, PIO>, 736 pub used_memory: InstanceMemory<'d, PIO>,
737 origin: u8, 737 pub origin: u8,
738 wrap: Wrap, 738 pub wrap: Wrap,
739 side_set: SideSet, 739 pub side_set: SideSet,
740}
741
742#[derive(Clone, Copy, PartialEq, Eq, Debug)]
743#[cfg_attr(feature = "defmt", derive(defmt::Format))]
744pub enum LoadError {
745 /// Insufficient consecutive free instruction space to load program.
746 InsufficientSpace,
747 /// Loading the program would overwrite an instruction address already
748 /// used by another program.
749 AddressInUse(usize),
740} 750}
741 751
742impl<'d, PIO: Instance> Common<'d, PIO> { 752impl<'d, PIO: Instance> Common<'d, PIO> {
743 pub fn load_program<const SIZE: usize>(&mut self, prog: &RelocatedProgram<SIZE>) -> LoadedProgram<'d, PIO> { 753 /// Load a PIO program. This will automatically relocate the program to
754 /// an available chunk of free instruction memory if the program origin
755 /// was not explicitly specified, otherwise it will attempt to load the
756 /// program only at its origin.
757 pub fn load_program<const SIZE: usize>(&mut self, prog: &Program<SIZE>) -> LoadedProgram<'d, PIO> {
744 match self.try_load_program(prog) { 758 match self.try_load_program(prog) {
745 Ok(r) => r, 759 Ok(r) => r,
746 Err(at) => panic!("Trying to write already used PIO instruction memory at {}", at), 760 Err(e) => panic!("Failed to load PIO program: {:?}", e),
747 } 761 }
748 } 762 }
749 763
764 /// Load a PIO program. This will automatically relocate the program to
765 /// an available chunk of free instruction memory if the program origin
766 /// was not explicitly specified, otherwise it will attempt to load the
767 /// program only at its origin.
750 pub fn try_load_program<const SIZE: usize>( 768 pub fn try_load_program<const SIZE: usize>(
751 &mut self, 769 &mut self,
752 prog: &RelocatedProgram<SIZE>, 770 prog: &Program<SIZE>,
771 ) -> Result<LoadedProgram<'d, PIO>, LoadError> {
772 match prog.origin {
773 Some(origin) => self
774 .try_load_program_at(prog, origin)
775 .map_err(|a| LoadError::AddressInUse(a)),
776 None => {
777 // naively search for free space, allowing wraparound since
778 // PIO does support that. with only 32 instruction slots it
779 // doesn't make much sense to do anything more fancy.
780 let mut origin = 0;
781 while origin < 32 {
782 match self.try_load_program_at(prog, origin as _) {
783 Ok(r) => return Ok(r),
784 Err(a) => origin = a + 1,
785 }
786 }
787 Err(LoadError::InsufficientSpace)
788 }
789 }
790 }
791
792 fn try_load_program_at<const SIZE: usize>(
793 &mut self,
794 prog: &Program<SIZE>,
795 origin: u8,
753 ) -> Result<LoadedProgram<'d, PIO>, usize> { 796 ) -> Result<LoadedProgram<'d, PIO>, usize> {
797 let prog = RelocatedProgram::new_with_origin(prog, origin);
754 let used_memory = self.try_write_instr(prog.origin() as _, prog.code())?; 798 let used_memory = self.try_write_instr(prog.origin() as _, prog.code())?;
755 Ok(LoadedProgram { 799 Ok(LoadedProgram {
756 used_memory, 800 used_memory,
@@ -760,7 +804,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
760 }) 804 })
761 } 805 }
762 806
763 pub fn try_write_instr<I>(&mut self, start: usize, instrs: I) -> Result<InstanceMemory<'d, PIO>, usize> 807 fn try_write_instr<I>(&mut self, start: usize, instrs: I) -> Result<InstanceMemory<'d, PIO>, usize>
764 where 808 where
765 I: Iterator<Item = u16>, 809 I: Iterator<Item = u16>,
766 { 810 {
diff --git a/embassy-rp/src/relocate.rs b/embassy-rp/src/relocate.rs
index 9cb279ccd..b35b4ed72 100644
--- a/embassy-rp/src/relocate.rs
+++ b/embassy-rp/src/relocate.rs
@@ -41,11 +41,6 @@ pub struct RelocatedProgram<'a, const PROGRAM_SIZE: usize> {
41} 41}
42 42
43impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> { 43impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> {
44 pub fn new(program: &Program<PROGRAM_SIZE>) -> RelocatedProgram<PROGRAM_SIZE> {
45 let origin = program.origin.unwrap_or(0);
46 RelocatedProgram { program, origin }
47 }
48
49 pub fn new_with_origin(program: &Program<PROGRAM_SIZE>, origin: u8) -> RelocatedProgram<PROGRAM_SIZE> { 44 pub fn new_with_origin(program: &Program<PROGRAM_SIZE>, origin: u8) -> RelocatedProgram<PROGRAM_SIZE> {
50 RelocatedProgram { program, origin } 45 RelocatedProgram { program, origin }
51 } 46 }