Last active
October 9, 2025 22:02
-
-
Save esden/919f4728471a47db5f63bff3f49e8c12 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #![no_std] | |
| #![no_main] | |
| use blackmagic_rust_firmware::{split_resources, system::preamble::*}; | |
| use defmt::*; | |
| use embassy_executor::Spawner; | |
| use embassy_stm32::{ospi::{self, Ospi}, rcc}; | |
| use embassy_time::Timer; | |
| use {defmt_rtt as _, panic_probe as _}; | |
| use embassy_stm32::pac::{OCTOSPI1, octospi::vals}; | |
| fn manual_init( | |
| ) { | |
| // System configuration | |
| rcc::enable_and_reset::<embassy_stm32::peripherals::OCTOSPI1>(); | |
| while OCTOSPI1.sr().read().busy() {} | |
| // Device configuration | |
| OCTOSPI1.dcr1().modify(|v| { | |
| v.set_devsize(5); // 16MBytes (128MBit) | |
| v.set_mtyp(vals::MemType::B_STANDARD); | |
| v.set_csht(2); | |
| v.set_dlybyp(true); | |
| v.set_frck(false); | |
| v.set_ckmode(false); | |
| }); | |
| OCTOSPI1.dcr2().modify(|v| { | |
| v.set_wrapsize(0); // None | |
| }); | |
| OCTOSPI1.dcr3().modify(|v| { | |
| v.set_csbound(0); | |
| v.set_maxtran(0); | |
| }); | |
| OCTOSPI1.dcr4().modify(|v| { | |
| v.set_refresh(0); | |
| }); | |
| OCTOSPI1.cr().modify(|v| v.set_fthres(vals::Threshold::_RESERVED_f)); | |
| // Wait for the busy flag to clear | |
| while OCTOSPI1.sr().read().busy() {} | |
| OCTOSPI1.dcr2().modify(|v| v.set_prescaler(255)); | |
| OCTOSPI1.cr().modify(|v| v.set_dmm(false)); | |
| OCTOSPI1.tcr().modify(|v| { | |
| v.set_sshift(vals::SampleShift::NONE); | |
| v.set_dhqc(false); | |
| }); | |
| OCTOSPI1.cr().modify(|v| v.set_en(true)); | |
| } | |
| fn dump_regs() { | |
| info!("SR {}", OCTOSPI1.sr().read()); | |
| info!("DCR1 {}", OCTOSPI1.dcr1().read()); | |
| info!("DCR2 {}", OCTOSPI1.dcr2().read()); | |
| info!("DCR3 {}", OCTOSPI1.dcr3().read()); | |
| info!("DCR4 {}", OCTOSPI1.dcr4().read()); | |
| info!("CR {}", OCTOSPI1.cr().read()); | |
| info!("TCR {}", OCTOSPI1.tcr().read()); | |
| } | |
| fn manual_read() { | |
| let dl = OCTOSPI1.dlr().read().dl(); | |
| let cr = OCTOSPI1.cr().read(); | |
| let ccr = OCTOSPI1.ccr().read(); | |
| let sr = OCTOSPI1.sr().read(); | |
| info!("DL {}", dl); | |
| info!("CR {}", cr); | |
| info!("CCR {}", ccr); | |
| info!("SR {}", sr); | |
| OCTOSPI1.cr().modify(|v| { | |
| v.set_dmaen(false); | |
| v.set_fthres(vals::Threshold::_RESERVED_f); | |
| v.set_fmode(vals::FunctionalMode::INDIRECT_READ); | |
| }); | |
| OCTOSPI1.dlr().write(|v| v.set_dl(0x2)); | |
| OCTOSPI1.tcr().write(|v| { | |
| v.set_dcyc(0); | |
| v.set_dhqc(false); | |
| v.set_sshift(vals::SampleShift::NONE); | |
| }); | |
| OCTOSPI1.ccr().write(|v| { | |
| v.set_imode(vals::PhaseMode::ONE_LINE); | |
| v.set_idtr(false); | |
| v.set_isize(vals::SizeInBits::_8BIT); | |
| v.set_admode(vals::PhaseMode::NONE); | |
| v.set_addtr(false); | |
| v.set_adsize(vals::SizeInBits::_8BIT); | |
| v.set_abmode(vals::PhaseMode::NONE); | |
| v.set_abdtr(false); | |
| v.set_absize(vals::SizeInBits::_8BIT); | |
| v.set_dmode(vals::PhaseMode::ONE_LINE); | |
| v.set_ddtr(false); | |
| v.set_dqse(false); | |
| v.set_sioo(false); | |
| }); | |
| OCTOSPI1.ir().write(|v| v.set_instruction(0x9F)); | |
| let mut status = OCTOSPI1.sr().read(); | |
| info!("SR {}", status); | |
| for n in 0..4 { | |
| // while status.busy() {} | |
| while !status.tcf() && !status.ftf() { | |
| status = OCTOSPI1.sr().read(); | |
| // info!("SR {}", status); | |
| } | |
| // OCTOSPI1.fcr().write(|v| v.set_ctcf(true)); | |
| // let val = OCTOSPI1.dr().read().data(); | |
| let val = unsafe { (OCTOSPI1.dr().as_ptr() as *mut u8).read_volatile() }; | |
| let new_status = OCTOSPI1.sr().read(); | |
| info!("n {} Sr {} val {:#04x} Sr {}", n, status, val, new_status); | |
| status = new_status; | |
| } | |
| while !OCTOSPI1.sr().read().tcf() {} | |
| OCTOSPI1.fcr().write(|v| v.set_ctcf(true)); | |
| } | |
| #[embassy_executor::main] | |
| async fn main(_spawner: Spawner) { | |
| info!("Hello World!"); | |
| let p = system::init(); | |
| let r = split_resources!(p); | |
| let _flash = system::get_flash_blocking(r.flash); | |
| dump_regs(); | |
| manual_init(/*r.flash*/); | |
| dump_regs(); | |
| // The flash chip that is connected here over SPI is the Winbond W25Q128 | |
| // Refer to the datasheet for protocol details | |
| loop { | |
| manual_read(); | |
| Timer::after_millis(10).await; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment