diff options
| -rw-r--r-- | embassy-rp/src/flash.rs | 135 | ||||
| -rw-r--r-- | embassy-rp/src/lib.rs | 4 | ||||
| -rw-r--r-- | examples/rp23/.cargo/config.toml | 3 | ||||
| -rw-r--r-- | examples/rp23/src/bin/flash.rs | 15 |
4 files changed, 68 insertions, 89 deletions
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 5f7922f8e..dab99b4e2 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs | |||
| @@ -17,9 +17,13 @@ use crate::peripherals::FLASH; | |||
| 17 | /// Flash base address. | 17 | /// Flash base address. |
| 18 | pub const FLASH_BASE: *const u32 = 0x10000000 as _; | 18 | pub const FLASH_BASE: *const u32 = 0x10000000 as _; |
| 19 | 19 | ||
| 20 | /// Address for xip setup function set up by the 235x bootrom. | ||
| 21 | #[cfg(feature = "_rp235x")] | ||
| 22 | pub const BOOTROM_BASE: *const u32 = 0x400e0000 as _; | ||
| 23 | |||
| 20 | /// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead. | 24 | /// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead. |
| 21 | // TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance. | 25 | // TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance. |
| 22 | pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram"); | 26 | pub const USE_BOOT2: bool = !cfg!(feature = "run-from-ram") | cfg!(feature = "_rp235x"); |
| 23 | 27 | ||
| 24 | // **NOTE**: | 28 | // **NOTE**: |
| 25 | // | 29 | // |
| @@ -97,7 +101,10 @@ impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Drop for BackgroundRead<'a, ' | |||
| 97 | // Errata RP2040-E8: Perform an uncached read to make sure there's not a transfer in | 101 | // Errata RP2040-E8: Perform an uncached read to make sure there's not a transfer in |
| 98 | // flight that might effect an address written to start a new transfer. This stalls | 102 | // flight that might effect an address written to start a new transfer. This stalls |
| 99 | // until after any transfer is complete, so the address will not change anymore. | 103 | // until after any transfer is complete, so the address will not change anymore. |
| 104 | #[cfg(feature = "rp2040")] | ||
| 100 | const XIP_NOCACHE_NOALLOC_BASE: *const u32 = 0x13000000 as *const _; | 105 | const XIP_NOCACHE_NOALLOC_BASE: *const u32 = 0x13000000 as *const _; |
| 106 | #[cfg(feature = "_rp235x")] | ||
| 107 | const XIP_NOCACHE_NOALLOC_BASE: *const u32 = 0x14000000 as *const _; | ||
| 101 | unsafe { | 108 | unsafe { |
| 102 | core::ptr::read_volatile(XIP_NOCACHE_NOALLOC_BASE); | 109 | core::ptr::read_volatile(XIP_NOCACHE_NOALLOC_BASE); |
| 103 | } | 110 | } |
| @@ -225,12 +232,14 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI | |||
| 225 | } | 232 | } |
| 226 | 233 | ||
| 227 | /// Read SPI flash unique ID | 234 | /// Read SPI flash unique ID |
| 235 | #[cfg(feature = "rp2040")] | ||
| 228 | pub fn blocking_unique_id(&mut self, uid: &mut [u8]) -> Result<(), Error> { | 236 | pub fn blocking_unique_id(&mut self, uid: &mut [u8]) -> Result<(), Error> { |
| 229 | unsafe { in_ram(|| ram_helpers::flash_unique_id(uid))? }; | 237 | unsafe { in_ram(|| ram_helpers::flash_unique_id(uid))? }; |
| 230 | Ok(()) | 238 | Ok(()) |
| 231 | } | 239 | } |
| 232 | 240 | ||
| 233 | /// Read SPI flash JEDEC ID | 241 | /// Read SPI flash JEDEC ID |
| 242 | #[cfg(feature = "rp2040")] | ||
| 234 | pub fn blocking_jedec_id(&mut self) -> Result<u32, Error> { | 243 | pub fn blocking_jedec_id(&mut self) -> Result<u32, Error> { |
| 235 | let mut jedec = None; | 244 | let mut jedec = None; |
| 236 | unsafe { | 245 | unsafe { |
| @@ -301,7 +310,10 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> { | |||
| 301 | // Use the XIP AUX bus port, rather than the FIFO register access (e.x. | 310 | // Use the XIP AUX bus port, rather than the FIFO register access (e.x. |
| 302 | // pac::XIP_CTRL.stream_fifo().as_ptr()) to avoid DMA stalling on | 311 | // pac::XIP_CTRL.stream_fifo().as_ptr()) to avoid DMA stalling on |
| 303 | // general XIP access. | 312 | // general XIP access. |
| 313 | #[cfg(feature = "rp2040")] | ||
| 304 | const XIP_AUX_BASE: *const u32 = 0x50400000 as *const _; | 314 | const XIP_AUX_BASE: *const u32 = 0x50400000 as *const _; |
| 315 | #[cfg(feature = "_rp235x")] | ||
| 316 | const XIP_AUX_BASE: *const u32 = 0x50500000 as *const _; | ||
| 305 | let transfer = unsafe { | 317 | let transfer = unsafe { |
| 306 | crate::dma::read( | 318 | crate::dma::read( |
| 307 | self.dma.as_mut().unwrap(), | 319 | self.dma.as_mut().unwrap(), |
| @@ -510,19 +522,14 @@ mod ram_helpers { | |||
| 510 | /// | 522 | /// |
| 511 | /// `addr` and `len` parameters must be valid and are not checked. | 523 | /// `addr` and `len` parameters must be valid and are not checked. |
| 512 | pub unsafe fn flash_range_erase(addr: u32, len: u32) { | 524 | pub unsafe fn flash_range_erase(addr: u32, len: u32) { |
| 513 | #[cfg(feature = "rp2040")] | ||
| 514 | let mut boot2 = [0u32; 256 / 4]; | 525 | let mut boot2 = [0u32; 256 / 4]; |
| 515 | let ptrs = { | 526 | let ptrs = if USE_BOOT2 { |
| 516 | #[cfg(feature = "rp2040")] | 527 | #[cfg(feature = "rp2040")] |
| 517 | { | 528 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); |
| 518 | if USE_BOOT2 { | ||
| 519 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); | ||
| 520 | flash_function_pointers_with_boot2(true, false, &boot2) | ||
| 521 | } else { | ||
| 522 | flash_function_pointers(true, false) | ||
| 523 | } | ||
| 524 | } | ||
| 525 | #[cfg(feature = "_rp235x")] | 529 | #[cfg(feature = "_rp235x")] |
| 530 | core::ptr::copy_nonoverlapping(BOOTROM_BASE as *const u8, boot2.as_mut_ptr() as *mut u8, 256); | ||
| 531 | flash_function_pointers_with_boot2(true, false, &boot2) | ||
| 532 | } else { | ||
| 526 | flash_function_pointers(true, false) | 533 | flash_function_pointers(true, false) |
| 527 | }; | 534 | }; |
| 528 | 535 | ||
| @@ -548,19 +555,14 @@ mod ram_helpers { | |||
| 548 | /// | 555 | /// |
| 549 | /// `addr` and `len` parameters must be valid and are not checked. | 556 | /// `addr` and `len` parameters must be valid and are not checked. |
| 550 | pub unsafe fn flash_range_erase_and_program(addr: u32, data: &[u8]) { | 557 | pub unsafe fn flash_range_erase_and_program(addr: u32, data: &[u8]) { |
| 551 | #[cfg(feature = "rp2040")] | ||
| 552 | let mut boot2 = [0u32; 256 / 4]; | 558 | let mut boot2 = [0u32; 256 / 4]; |
| 553 | let ptrs = { | 559 | let ptrs = if USE_BOOT2 { |
| 554 | #[cfg(feature = "rp2040")] | 560 | #[cfg(feature = "rp2040")] |
| 555 | { | 561 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); |
| 556 | if USE_BOOT2 { | ||
| 557 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); | ||
| 558 | flash_function_pointers_with_boot2(true, true, &boot2) | ||
| 559 | } else { | ||
| 560 | flash_function_pointers(true, true) | ||
| 561 | } | ||
| 562 | } | ||
| 563 | #[cfg(feature = "_rp235x")] | 562 | #[cfg(feature = "_rp235x")] |
| 563 | core::ptr::copy_nonoverlapping(BOOTROM_BASE as *const u8, (boot2).as_mut_ptr() as *mut u8, 256); | ||
| 564 | flash_function_pointers_with_boot2(true, true, &boot2) | ||
| 565 | } else { | ||
| 564 | flash_function_pointers(true, true) | 566 | flash_function_pointers(true, true) |
| 565 | }; | 567 | }; |
| 566 | 568 | ||
| @@ -591,19 +593,14 @@ mod ram_helpers { | |||
| 591 | /// | 593 | /// |
| 592 | /// `addr` and `len` parameters must be valid and are not checked. | 594 | /// `addr` and `len` parameters must be valid and are not checked. |
| 593 | pub unsafe fn flash_range_program(addr: u32, data: &[u8]) { | 595 | pub unsafe fn flash_range_program(addr: u32, data: &[u8]) { |
| 594 | #[cfg(feature = "rp2040")] | ||
| 595 | let mut boot2 = [0u32; 256 / 4]; | 596 | let mut boot2 = [0u32; 256 / 4]; |
| 596 | let ptrs = { | 597 | let ptrs = if USE_BOOT2 { |
| 597 | #[cfg(feature = "rp2040")] | 598 | #[cfg(feature = "rp2040")] |
| 598 | { | 599 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); |
| 599 | if USE_BOOT2 { | ||
| 600 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); | ||
| 601 | flash_function_pointers_with_boot2(false, true, &boot2) | ||
| 602 | } else { | ||
| 603 | flash_function_pointers(false, true) | ||
| 604 | } | ||
| 605 | } | ||
| 606 | #[cfg(feature = "_rp235x")] | 600 | #[cfg(feature = "_rp235x")] |
| 601 | core::ptr::copy_nonoverlapping(BOOTROM_BASE as *const u8, boot2.as_mut_ptr() as *mut u8, 256); | ||
| 602 | flash_function_pointers_with_boot2(false, true, &boot2) | ||
| 603 | } else { | ||
| 607 | flash_function_pointers(false, true) | 604 | flash_function_pointers(false, true) |
| 608 | }; | 605 | }; |
| 609 | 606 | ||
| @@ -630,16 +627,7 @@ mod ram_helpers { | |||
| 630 | #[link_section = ".data.ram_func"] | 627 | #[link_section = ".data.ram_func"] |
| 631 | #[cfg(feature = "rp2040")] | 628 | #[cfg(feature = "rp2040")] |
| 632 | unsafe fn write_flash_inner(addr: u32, len: u32, data: Option<&[u8]>, ptrs: *const FlashFunctionPointers) { | 629 | unsafe fn write_flash_inner(addr: u32, len: u32, data: Option<&[u8]>, ptrs: *const FlashFunctionPointers) { |
| 633 | /* | 630 | //#[cfg(target_arch = "arm")] |
| 634 | Should be equivalent to: | ||
| 635 | rom_data::connect_internal_flash(); | ||
| 636 | rom_data::flash_exit_xip(); | ||
| 637 | rom_data::flash_range_erase(addr, len, 1 << 31, 0); // if selected | ||
| 638 | rom_data::flash_range_program(addr, data as *const _, len); // if selected | ||
| 639 | rom_data::flash_flush_cache(); | ||
| 640 | rom_data::flash_enter_cmd_xip(); | ||
| 641 | */ | ||
| 642 | #[cfg(target_arch = "arm")] | ||
| 643 | core::arch::asm!( | 631 | core::arch::asm!( |
| 644 | "mov r8, r0", | 632 | "mov r8, r0", |
| 645 | "mov r9, r2", | 633 | "mov r9, r2", |
| @@ -691,11 +679,30 @@ mod ram_helpers { | |||
| 691 | ); | 679 | ); |
| 692 | } | 680 | } |
| 693 | 681 | ||
| 682 | /// # Safety | ||
| 683 | /// | ||
| 684 | /// Nothing must access flash while this is running. | ||
| 685 | /// Usually this means: | ||
| 686 | /// - interrupts must be disabled | ||
| 687 | /// - 2nd core must be running code from RAM or ROM with interrupts disabled | ||
| 688 | /// - DMA must not access flash memory | ||
| 689 | /// Length of data must be a multiple of 4096 | ||
| 690 | /// addr must be aligned to 4096 | ||
| 694 | #[inline(never)] | 691 | #[inline(never)] |
| 695 | #[link_section = ".data.ram_func"] | 692 | #[link_section = ".data.ram_func"] |
| 696 | #[cfg(feature = "_rp235x")] | 693 | #[cfg(feature = "_rp235x")] |
| 697 | unsafe fn write_flash_inner(_addr: u32, _len: u32, _data: Option<&[u8]>, _ptrs: *const FlashFunctionPointers) { | 694 | unsafe fn write_flash_inner(addr: u32, len: u32, data: Option<&[u8]>, ptrs: *const FlashFunctionPointers) { |
| 698 | todo!(); | 695 | let data = data.map(|d| d.as_ptr()).unwrap_or(core::ptr::null()); |
| 696 | ((*ptrs).connect_internal_flash)(); | ||
| 697 | ((*ptrs).flash_exit_xip)(); | ||
| 698 | if (*ptrs).flash_range_erase.is_some() { | ||
| 699 | ((*ptrs).flash_range_erase.unwrap())(addr, len as usize, 1 << 31, 0); | ||
| 700 | } | ||
| 701 | if (*ptrs).flash_range_program.is_some() { | ||
| 702 | ((*ptrs).flash_range_program.unwrap())(addr, data as *const _, len as usize); | ||
| 703 | } | ||
| 704 | ((*ptrs).flash_flush_cache)(); | ||
| 705 | ((*ptrs).flash_enter_cmd_xip)(); | ||
| 699 | } | 706 | } |
| 700 | 707 | ||
| 701 | #[repr(C)] | 708 | #[repr(C)] |
| @@ -731,20 +738,13 @@ mod ram_helpers { | |||
| 731 | /// - DMA must not access flash memory | 738 | /// - DMA must not access flash memory |
| 732 | /// | 739 | /// |
| 733 | /// Credit: taken from `rp2040-flash` (also licensed Apache+MIT) | 740 | /// Credit: taken from `rp2040-flash` (also licensed Apache+MIT) |
| 741 | #[cfg(feature = "rp2040")] | ||
| 734 | pub unsafe fn flash_unique_id(out: &mut [u8]) { | 742 | pub unsafe fn flash_unique_id(out: &mut [u8]) { |
| 735 | #[cfg(feature = "rp2040")] | ||
| 736 | let mut boot2 = [0u32; 256 / 4]; | 743 | let mut boot2 = [0u32; 256 / 4]; |
| 737 | let ptrs = { | 744 | let ptrs = if USE_BOOT2 { |
| 738 | #[cfg(feature = "rp2040")] | 745 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); |
| 739 | { | 746 | flash_function_pointers_with_boot2(false, false, &boot2) |
| 740 | if USE_BOOT2 { | 747 | } else { |
| 741 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); | ||
| 742 | flash_function_pointers_with_boot2(false, false, &boot2) | ||
| 743 | } else { | ||
| 744 | flash_function_pointers(false, false) | ||
| 745 | } | ||
| 746 | } | ||
| 747 | #[cfg(feature = "_rp235x")] | ||
| 748 | flash_function_pointers(false, false) | 748 | flash_function_pointers(false, false) |
| 749 | }; | 749 | }; |
| 750 | 750 | ||
| @@ -768,20 +768,13 @@ mod ram_helpers { | |||
| 768 | /// - DMA must not access flash memory | 768 | /// - DMA must not access flash memory |
| 769 | /// | 769 | /// |
| 770 | /// Credit: taken from `rp2040-flash` (also licensed Apache+MIT) | 770 | /// Credit: taken from `rp2040-flash` (also licensed Apache+MIT) |
| 771 | #[cfg(feature = "rp2040")] | ||
| 771 | pub unsafe fn flash_jedec_id() -> u32 { | 772 | pub unsafe fn flash_jedec_id() -> u32 { |
| 772 | #[cfg(feature = "rp2040")] | ||
| 773 | let mut boot2 = [0u32; 256 / 4]; | 773 | let mut boot2 = [0u32; 256 / 4]; |
| 774 | let ptrs = { | 774 | let ptrs = if USE_BOOT2 { |
| 775 | #[cfg(feature = "rp2040")] | 775 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); |
| 776 | { | 776 | flash_function_pointers_with_boot2(false, false, &boot2) |
| 777 | if USE_BOOT2 { | 777 | } else { |
| 778 | rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256); | ||
| 779 | flash_function_pointers_with_boot2(false, false, &boot2) | ||
| 780 | } else { | ||
| 781 | flash_function_pointers(false, false) | ||
| 782 | } | ||
| 783 | } | ||
| 784 | #[cfg(feature = "_rp235x")] | ||
| 785 | flash_function_pointers(false, false) | 778 | flash_function_pointers(false, false) |
| 786 | }; | 779 | }; |
| 787 | 780 | ||
| @@ -792,6 +785,7 @@ mod ram_helpers { | |||
| 792 | u32::from_be_bytes(id) | 785 | u32::from_be_bytes(id) |
| 793 | } | 786 | } |
| 794 | 787 | ||
| 788 | #[cfg(feature = "rp2040")] | ||
| 795 | unsafe fn read_flash(cmd_addr: &[u8], dummy_len: u32, out: &mut [u8], ptrs: *const FlashFunctionPointers) { | 789 | unsafe fn read_flash(cmd_addr: &[u8], dummy_len: u32, out: &mut [u8], ptrs: *const FlashFunctionPointers) { |
| 796 | read_flash_inner( | 790 | read_flash_inner( |
| 797 | FlashCommand { | 791 | FlashCommand { |
| @@ -932,13 +926,6 @@ mod ram_helpers { | |||
| 932 | clobber_abi("C"), | 926 | clobber_abi("C"), |
| 933 | ); | 927 | ); |
| 934 | } | 928 | } |
| 935 | |||
| 936 | #[inline(never)] | ||
| 937 | #[link_section = ".data.ram_func"] | ||
| 938 | #[cfg(feature = "_rp235x")] | ||
| 939 | unsafe fn read_flash_inner(_cmd: FlashCommand, _ptrs: *const FlashFunctionPointers) { | ||
| 940 | todo!(); | ||
| 941 | } | ||
| 942 | } | 929 | } |
| 943 | 930 | ||
| 944 | /// Make sure to uphold the contract points with rp2040-flash. | 931 | /// Make sure to uphold the contract points with rp2040-flash. |
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index c2c57eaa0..f8fcfe52b 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs | |||
| @@ -402,7 +402,7 @@ embassy_hal_internal::peripherals! { | |||
| 402 | BOOTSEL, | 402 | BOOTSEL, |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | #[cfg(not(feature = "boot2-none"))] | 405 | #[cfg(all(not(feature = "boot2-none"), feature = "rp2040"))] |
| 406 | macro_rules! select_bootloader { | 406 | macro_rules! select_bootloader { |
| 407 | ( $( $feature:literal => $loader:ident, )+ default => $default:ident ) => { | 407 | ( $( $feature:literal => $loader:ident, )+ default => $default:ident ) => { |
| 408 | $( | 408 | $( |
| @@ -419,7 +419,7 @@ macro_rules! select_bootloader { | |||
| 419 | } | 419 | } |
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | #[cfg(not(feature = "boot2-none"))] | 422 | #[cfg(all(not(feature = "boot2-none"), feature = "rp2040"))] |
| 423 | select_bootloader! { | 423 | select_bootloader! { |
| 424 | "boot2-at25sf128a" => BOOT_LOADER_AT25SF128A, | 424 | "boot2-at25sf128a" => BOOT_LOADER_AT25SF128A, |
| 425 | "boot2-gd25q64cs" => BOOT_LOADER_GD25Q64CS, | 425 | "boot2-gd25q64cs" => BOOT_LOADER_GD25Q64CS, |
diff --git a/examples/rp23/.cargo/config.toml b/examples/rp23/.cargo/config.toml index f77e004dc..9a92b1ce2 100644 --- a/examples/rp23/.cargo/config.toml +++ b/examples/rp23/.cargo/config.toml | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | #runner = "probe-rs run --chip RP2040" | 2 | #runner = "probe-rs run --chip RP2040" |
| 3 | runner = "elf2uf2-rs -d" | 3 | #runner = "elf2uf2-rs -d" |
| 4 | runner = "picotool load -u -v -x -t elf" | ||
| 4 | 5 | ||
| 5 | [build] | 6 | [build] |
| 6 | target = "thumbv8m.main-none-eabihf" | 7 | target = "thumbv8m.main-none-eabihf" |
diff --git a/examples/rp23/src/bin/flash.rs b/examples/rp23/src/bin/flash.rs index 811561f26..84011e394 100644 --- a/examples/rp23/src/bin/flash.rs +++ b/examples/rp23/src/bin/flash.rs | |||
| @@ -21,7 +21,7 @@ pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); | |||
| 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ | 21 | pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [ |
| 22 | embassy_rp::binary_info::rp_program_name!(c"example"), | 22 | embassy_rp::binary_info::rp_program_name!(c"example"), |
| 23 | embassy_rp::binary_info::rp_cargo_version!(), | 23 | embassy_rp::binary_info::rp_cargo_version!(), |
| 24 | embassy_rp::binary_info::rp_program_description!(c"Blinky"), | 24 | embassy_rp::binary_info::rp_program_description!(c"Flash"), |
| 25 | embassy_rp::binary_info::rp_program_build_attribute!(), | 25 | embassy_rp::binary_info::rp_program_build_attribute!(), |
| 26 | ]; | 26 | ]; |
| 27 | 27 | ||
| @@ -41,22 +41,13 @@ async fn main(_spawner: Spawner) { | |||
| 41 | 41 | ||
| 42 | let mut flash = embassy_rp::flash::Flash::<_, Async, FLASH_SIZE>::new(p.FLASH, p.DMA_CH0); | 42 | let mut flash = embassy_rp::flash::Flash::<_, Async, FLASH_SIZE>::new(p.FLASH, p.DMA_CH0); |
| 43 | 43 | ||
| 44 | // Get JEDEC id | ||
| 45 | let jedec = flash.blocking_jedec_id().unwrap(); | ||
| 46 | info!("jedec id: 0x{:x}", jedec); | ||
| 47 | |||
| 48 | // Get unique id | ||
| 49 | let mut uid = [0; 8]; | ||
| 50 | flash.blocking_unique_id(&mut uid).unwrap(); | ||
| 51 | info!("unique id: {:?}", uid); | ||
| 52 | |||
| 53 | erase_write_sector(&mut flash, 0x00); | 44 | erase_write_sector(&mut flash, 0x00); |
| 54 | 45 | ||
| 55 | multiwrite_bytes(&mut flash, ERASE_SIZE as u32); | 46 | multiwrite_bytes(&mut flash, ERASE_SIZE as u32); |
| 56 | 47 | ||
| 57 | background_read(&mut flash, (ERASE_SIZE * 2) as u32).await; | 48 | background_read(&mut flash, (ERASE_SIZE * 2) as u32).await; |
| 58 | 49 | ||
| 59 | loop {} | 50 | info!("Flash Works!"); |
| 60 | } | 51 | } |
| 61 | 52 | ||
| 62 | fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) { | 53 | fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) { |
| @@ -82,7 +73,7 @@ fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH | |||
| 82 | 73 | ||
| 83 | defmt::unwrap!(flash.blocking_read(ADDR_OFFSET + offset, &mut read_buf)); | 74 | defmt::unwrap!(flash.blocking_read(ADDR_OFFSET + offset, &mut read_buf)); |
| 84 | info!("Contents after write starts with {=[u8]}", read_buf[0..4]); | 75 | info!("Contents after write starts with {=[u8]}", read_buf[0..4]); |
| 85 | if &read_buf[0..4] != &[0x01, 0x02, 0x03, 0x04] { | 76 | if read_buf[0..4] != [0x01, 0x02, 0x03, 0x04] { |
| 86 | defmt::panic!("unexpected"); | 77 | defmt::panic!("unexpected"); |
| 87 | } | 78 | } |
| 88 | } | 79 | } |
