use super::{StackError, WincClient, Xfer};
use crate::manager::FLASH_PAGE_SIZE;
use crate::{error, info};
const FLASH_BLOCK_SIZE: usize = 32 * 1024;
const CHIP_REV_LP: u32 = 0x3A0;
impl<X: Xfer> WincClient<'_, X> {
pub fn set_flash_access(&mut self, enable: bool) -> Result<(), StackError> {
let mut chip_id = self.manager.chip_id()?;
chip_id &= 0x00000fff;
if chip_id >= CHIP_REV_LP {
if enable {
self.manager.send_flash_pin_mux(true)?;
self.manager.send_flash_low_power_mode(false)?;
} else {
self.manager.send_flash_pin_mux(false)?;
self.manager.send_flash_low_power_mode(true)?;
}
}
Ok(())
}
pub fn flash_read(&mut self, addr: u32, buffer: &mut [u8]) -> Result<(), StackError> {
if buffer.is_empty() {
return Err(StackError::InvalidParameters);
}
let mut offset: usize = 0;
let mut flash_addr = addr;
loop {
let to_recv = (buffer[offset..]).len().min(FLASH_BLOCK_SIZE);
self.manager
.send_flash_read(flash_addr, &mut buffer[offset..offset + to_recv])?;
offset += to_recv;
if offset >= buffer.len() {
return Ok(());
} else {
flash_addr += to_recv as u32;
}
}
}
pub fn flash_write(&mut self, addr: u32, data: &[u8]) -> Result<(), StackError> {
if data.is_empty() {
return Err(StackError::InvalidParameters);
}
let page_offset = addr as usize % FLASH_PAGE_SIZE; let mut offset: usize = 0; let mut flash_addr = addr;
if page_offset > 0 {
let word_size = FLASH_PAGE_SIZE - page_offset;
let valid_size = data.len().min(word_size);
self.manager
.send_flash_write(flash_addr, &data[..valid_size])?;
if data.len() <= word_size {
return Ok(());
}
offset += word_size;
flash_addr += word_size as u32;
}
while offset < data.len() {
let word_size = data[offset..].len().min(FLASH_PAGE_SIZE);
self.manager
.send_flash_write(flash_addr, &data[offset..offset + word_size])?;
offset += word_size;
flash_addr += word_size as u32;
}
Ok(())
}
pub fn flash_erase(&mut self, addr: u32, size: u32) -> Result<(), StackError> {
if size == 0 {
return Ok(());
}
const SECTOR_SIZE: u32 = (16 * FLASH_PAGE_SIZE) as u32; let end = addr
.checked_add(size)
.ok_or(StackError::InvalidParameters)?;
let mut flash_addr: u32 = addr;
while flash_addr < end {
let mut retries: u8 = 3;
self.manager.send_flash_write_access(true)?;
let _ = self.manager.send_flash_read_status_register()?;
self.manager.send_flash_erase_sector(flash_addr + 10)?;
let mut val = self.manager.send_flash_read_status_register()?;
while (val & 0x01) != 0 {
if retries == 0 {
error!(
"Erasing flash sector failed due to invalid flash status register value."
);
return Err(StackError::GeneralTimeout);
}
retries -= 1;
val = self.manager.send_flash_read_status_register()?;
}
flash_addr = flash_addr.saturating_add(SECTOR_SIZE);
}
self.manager.send_flash_write_access(false)?;
Ok(())
}
pub fn flash_get_size(&mut self) -> Result<u32, StackError> {
const FLASH_ID_SIZE_OFFSET: u32 = 0x11;
let id = self.manager.send_flash_read_id()?;
if id == 0xffffffff {
error!("Unable to read the flash ID.");
return Err(StackError::Unexpected);
}
info!("The flash ID: {:x}", id);
let size_info = (id >> 16) & 0xFF;
if size_info < FLASH_ID_SIZE_OFFSET || size_info - FLASH_ID_SIZE_OFFSET >= 32 {
error!("Invalid flash ID.");
return Err(StackError::Unexpected);
}
let flash_size = 1u32 << (size_info - FLASH_ID_SIZE_OFFSET);
Ok(flash_size)
}
}