Skip to content

Commit

Permalink
Add Strage Stack Support
Browse files Browse the repository at this point in the history
- Generic Storage Traits
- Flexspi NOR Storage Bus Driver
- SPI NOR Storage Bus Driver
- Example Storage Service
  • Loading branch information
Shaibal-Microsoft committed Mar 7, 2025
1 parent 66949e8 commit 65a51fa
Show file tree
Hide file tree
Showing 8 changed files with 2,285 additions and 12 deletions.
18 changes: 12 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ default = ["mimxrt685s", "rt"]
## [`rp-pac`](https://docs.rs/crates/rp-pac). This brings in the
## [`cortex-m-rt`](https://docs.rs/cortex-m-rt) crate, which adds
## startup code and minimal runtime initialization.
rt = [
"mimxrt685s-pac?/rt",
"mimxrt633s-pac?/rt",
]
rt = ["mimxrt685s-pac?/rt", "mimxrt633s-pac?/rt"]

## Enable [defmt support](https://docs.rs/defmt) and enables `defmt`
## debug-log messages and formatting in embassy drivers.
Expand Down Expand Up @@ -87,13 +84,22 @@ embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = [
embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
embedded-hal-async = { version = "1.0" }
embedded-hal-nb = { version = "1.0" }
mimxrt600-fcb = "0.1.0"

document-features = "0.2.7"
paste = "1.0"

# PACs
mimxrt685s-pac = { version = "0.2.2", optional = true, features = ["rt", "critical-section", "defmt"] }
mimxrt633s-pac = { version = "0.2.0", optional = true, features = ["rt", "critical-section", "defmt"] }
mimxrt685s-pac = { version = "0.2.2", optional = true, features = [
"rt",
"critical-section",
"defmt",
] }
mimxrt633s-pac = { version = "0.2.0", optional = true, features = [
"rt",
"critical-section",
"defmt",
] }

[dev-dependencies]
embassy-executor = { git = "https://github.com/embassy-rs/embassy" }
Expand Down
2 changes: 2 additions & 0 deletions examples/rt685s-evk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ embedded-hal-async = "1.0.0"
futures = { version = "0.3.30", default-features = false, features = [
"async-await",
] }
embedded-storage = { version = "0.3" }
embedded-storage-async = { version = "0.4.1" }
mimxrt600-fcb = "0.1.0"
rand = { version = "0.8.5", default-features = false }

Expand Down
23 changes: 17 additions & 6 deletions examples/rt685s-evk/memory.x
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,43 @@ MEMORY {
FCB : ORIGIN = 0x08000400, LENGTH = 512
BIV : ORIGIN = 0x08000600, LENGTH = 4
KEYSTORE : ORIGIN = 0x08000800, LENGTH = 2K
FLASH : ORIGIN = 0x08001000, LENGTH = 1M
FLASH : ORIGIN = 0x08001000, LENGTH = 1004K
FLEXSPIFLASH: ORIGIN = 0x080FC000, LENGTH = 10K
RAM : ORIGIN = 0x20080000, LENGTH = 1536K
FLEXSPIRAM: ORIGIN = 0x0, LENGTH = 10K
}


__flexspi_ram_start_addr__ = ORIGIN(FLEXSPIRAM);
__flexspi_flash_start_addr__ = ORIGIN(FLEXSPIFLASH);
__flexspi_flash_end_addr__ = ORIGIN(FLEXSPIFLASH) + LENGTH(FLEXSPIFLASH);


SECTIONS {
.otfad : {
. = ALIGN(4);
KEEP(* (.otfad))
. = ALIGN(4);
} > OTFAD

.fcb : {
. = ALIGN(4);
KEEP(* (.fcb))
. = ALIGN(4);
} > FCB

.biv : {
. = ALIGN(4);
KEEP(* (.biv))
. = ALIGN(4);
} > BIV

.keystore : {
. = ALIGN(4);
KEEP(* (.keystore))
. = ALIGN(4);
} > KEYSTORE
}

.flexspi_code : {
* (.flexspi_code)
} >FLEXSPIRAM AT>FLEXSPIFLASH
}
247 changes: 247 additions & 0 deletions examples/rt685s-evk/src/bin/flexspi-storage-service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
#![no_std]
#![no_main]

use defmt::{assert, info};
use embassy_executor::Spawner;
use embassy_imxrt::flexspi_nor_storage_bus::{
AhbConfig, FlexSpiBusWidth, FlexSpiFlashPort, FlexSpiFlashPortDeviceInstance, FlexspiAhbBufferConfig,
FlexspiAhbWriteWaitUnit, FlexspiConfig, FlexspiCsIntervalCycleUnit, FlexspiDeviceConfig, FlexspiNorStorageBus,
FlexspiReadSampleClock,
};
use embassy_imxrt::storage::{
BlockingNorStorageDriver, NorStorageCmd, NorStorageCmdMode, NorStorageCmdSeq, NorStorageCmdType,
};
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};

static ADDR: u32 = 0x2000;

struct MacronixDeviceDriver<T: BlockingNorStorageDriver> {
// Bus driver dependency
storagebusdriver: T,
}

impl<T: BlockingNorStorageDriver> MacronixDeviceDriver<T> {
pub fn new(storagebusdriver: T) -> Result<Self, ()> {
Ok(Self { storagebusdriver })
}

pub fn init(&self) {
let bus_ref = &self.storagebusdriver;
let cmdarr = NorStorageCmdSeq {
fast_read: Some(NorStorageCmd {
cmd_lb: 0xEE,
cmd_ub: Some(0x11),
addr_width: Some(4),
mode: NorStorageCmdMode::DDR,
dummy: Some(20),
cmdtype: Some(NorStorageCmdType::Read),
data_bytes: Some(1),
}),
page_program: Some(NorStorageCmd {
cmd_lb: 0x12,
cmd_ub: Some(0xED),
addr_width: Some(4),
mode: NorStorageCmdMode::DDR,
dummy: None,
cmdtype: Some(NorStorageCmdType::Write),
data_bytes: Some(1),
}),
sector_erase: Some(NorStorageCmd {
cmd_lb: 0x21,
cmd_ub: Some(0xDE),
addr_width: Some(4),
mode: NorStorageCmdMode::DDR,
dummy: None,
cmdtype: None,
data_bytes: None,
}),
write_enable: Some(NorStorageCmd {
cmd_lb: 0x06,
cmd_ub: Some(0xF9),
addr_width: None,
mode: NorStorageCmdMode::DDR,
dummy: None,
cmdtype: None,
data_bytes: None,
}),
write_disable: None,
read_id: Some(NorStorageCmd {
cmd_lb: 0x9F,
cmd_ub: Some(0x60),
addr_width: Some(4),
mode: NorStorageCmdMode::DDR,
dummy: None,
cmdtype: Some(NorStorageCmdType::Read),
data_bytes: Some(3),
}),
poweup: None,
powerdonw: None,
read_status_reg: Some(NorStorageCmd {
cmd_lb: 0x05,
cmd_ub: Some(0xFA),
addr_width: Some(4),
mode: NorStorageCmdMode::DDR,
dummy: Some(0x14),
cmdtype: Some(NorStorageCmdType::Read),
data_bytes: Some(1),
}),
write_status_reg: None,
read_cfg_reg1: None,
write_cfg_reg1: None,
read_cfg_reg2: None,
write_cfg_reg2: None,
read_cfg_reg3: None,
write_cfg_reg3: None,
chip_erase: None,
};

// Register the Cmd table with FlexSPI Storage
bus_ref.configure_cmd_seq(&cmdarr);
}

pub fn read(&mut self, addr: u32, data: &mut [u8]) {
let bus_ref = &mut self.storagebusdriver;
// Read data from the storage device
bus_ref.read(addr as u32, data);
}

pub fn write(&mut self, addr: u32, data: &[u8]) {
let bus_ref = &mut self.storagebusdriver;

let status_reg = bus_ref.read_status_reg().unwrap();
info!("status reg byte 0 = {}", status_reg[0]);
info!("status reg byte 1 = {}", status_reg[1]);
info!("status reg byte 2 = {}", status_reg[2]);
// Write data to the storage device
// bus_ref.write_enable();

// bus_ref.erase(addr, addr + data.len() as u32);

// bus_ref.write_enable();

// let data_size = data.len();
// for i in 0..data_size {
// bus_ref.write(addr + i as u32, &data);
// bus_ref.write_enable();
// }
}
}

#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_imxrt::init(Default::default());

// Consider this is a storage service or file system service
// As per the design, this service is supposed to instantiate low level bus object and configure the bus
// and pass it to the storage device driver when creating it as a dependency injection
// Bus drivers -
// 1. FlexspiNorStorageBus
// 2. SpiNorStorageBus

let mut read_data = [0_u8; 32];
let mut write_data = [0_u8; 32];
let flash_config = FlexspiDeviceConfig {
flexspi_root_clk: 48000000,
is_sck2_enabled: false,
// Flash size in this struct is in KB, so divide by 1KB
flash_size_kb: 0x10000, // 64 MB
cs_interval_unit: FlexspiCsIntervalCycleUnit::CsIntervalUnit1Cycle,
cs_interval: 2,
cs_hold_time: 3,
cs_setup_time: 3,
data_valid_time: 2,
columnspace: 0,
enable_word_address: false,
awr_seq_index: 1,
awr_seq_number: 0,
ard_seq_index: 0,
ard_seq_number: 0,
ahb_write_wait_unit: FlexspiAhbWriteWaitUnit::FlexspiAhbWriteWaitUnit2ahbCycle,
ahb_write_wait_interval: 0,
enable_write_mask: false,
};
let ahb_buffer_config = FlexspiAhbBufferConfig {
priority: 0,
master_index: 0,
buffer_size: 256,
enable_prefetch: true,
};

let ahb_config = AhbConfig {
enable_ahb_write_ip_rx_fifo: false,
enable_ahb_write_ip_tx_fifo: false,
ahb_grant_timeout_cycle: 0xff,
ahb_bus_timeout_cycle: 0xffff,
resume_wait_cycle: 0x20,
buffer: [ahb_buffer_config; 8],
enable_clear_ahb_buffer_opt: false,
enable_read_address_opt: true,
enable_ahb_prefetch: true,
enable_ahb_bufferable: true,
enable_ahb_cachable: true,
};

let flexspi_config = FlexspiConfig {
rx_sample_clock: FlexspiReadSampleClock::FlexspiReadSampleClkLoopbackInternally,
enable_sck_free_running: false,
enable_combination: false,
enable_doze: false, // TODO - Check back after analyzing system low power mode requirements
enable_half_speed_access: false,
enable_sck_b_diff_opt: false,
enable_same_config_for_all: false,
seq_timeout_cycle: 0xFFFF,
ip_grant_timeout_cycle: 0xff,
tx_watermark: 0x08,
rx_watermark: 0x08,
ahb_config,
};

let mut flexspi_storage = FlexspiNorStorageBus::new_blocking(
p.FLEXSPI, // FlexSPI peripheral
Some(p.PIO1_11), // FlexSPI DATA 0 pin
Some(p.PIO1_12),
Some(p.PIO1_13),
Some(p.PIO1_14),
Some(p.PIO2_17),
Some(p.PIO2_18),
Some(p.PIO2_22),
Some(p.PIO2_23),
p.PIO1_29,
p.PIO2_19,
FlexSpiFlashPort::PortB, // FlexSPI port
FlexSpiBusWidth::Octal, // FlexSPI bus width
FlexSpiFlashPortDeviceInstance::DeviceInstance0, // FlexSPI device instance
);

// flexspi_storage.configport.configure_flexspi(&flexspi_config); // Configure the Flexspi controller

// flexspi_storage
// .configport
// .configure_flexspi_device(&flash_config, &flexspi_config); // Configure the Flash device specific parameters like CS time, etc

// Instanctiate the storage device driver and inject the bus driver dependency
let mut device_driver = MacronixDeviceDriver::new(flexspi_storage).unwrap();
device_driver.init();

// write data
// device_driver.write(ADDR, &write_data);

info!("Array before reading");
for i in 0..5 {
info!("data[{}]: {}", i, read_data[i]);
}
device_driver.read(ADDR, &mut read_data);

info!("Array after reading");

for i in 0..5 {
info!("data[{}]: {}", i, read_data[i]);
}

device_driver.write(ADDR, &write_data);

loop {
Timer::after_millis(2000).await;
}
}
Loading

0 comments on commit 65a51fa

Please sign in to comment.