-
Notifications
You must be signed in to change notification settings - Fork 5
Spi dma irq #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Spi dma irq #36
Conversation
|
Can you create a PR? |
Done |
Add traits for spimonitor for public access
|
Location: pub struct SpiNorData<'a> {
pub mode: Jesd216Mode,
pub opcode: u32,
pub dummy_cycle: u32,
pub addr_len: u32,
pub addr: u32,
pub data_len: u32, // Comment says "not in used" in several places
pub tx_buf: &'a [u8],
pub rx_buf: &'a mut [u8],
pub data_direct: u32, // Uses magic constants SPI_NOR_DATA_DIRECT_READ/WRITE
}Problems:
Recommended fix: pub enum DataDirection {
Read,
Write,
None,
}
pub struct SpiNorCommand<'a> {
pub mode: Jesd216Mode,
pub opcode: u8, // Commands are 8-bit
pub address: Option<FlashAddress>,
pub dummy_cycles: u8,
pub data: TransferData<'a>,
}
pub enum TransferData<'a> {
Read(&'a mut [u8]),
Write(&'a [u8]),
None,
}
pub struct FlashAddress {
pub value: u32,
pub width: AddressWidth,
}
pub enum AddressWidth {
ThreeByte,
FourByte,
} |
|
Location:
Problem: Single Responsibility Principle violation. Makes testing, modification, and reasoning about the code difficult. Recommended decomposition: // Low-level register access
struct SpiRegisters {
regs: &'static ast1060_pac::spi::RegisterBlock,
}
// DMA operations
struct SpiDma<'a> {
regs: &'a SpiRegisters,
}
// Timing calibration
struct SpiCalibration<'a> {
regs: &'a SpiRegisters,
dma: &'a mut SpiDma<'a>,
}
// High-level controller combining components
pub struct SpiController<'a> {
regs: SpiRegisters,
dma: SpiDma<'a>,
config: SpiConfig,
state: SpiData,
} |
|
Location: pub fn spi_cal_dummy_cycle(bus_width: u32, dummy_cycle: u32) -> u32 {
let dummy_byte = dummy_cycle / (8 / bus_width); // Panics if bus_width == 0 or bus_width > 8
//...
}Risk scenarios:
Fix: pub fn spi_cal_dummy_cycle(bus_width: u32, dummy_cycle: u32) -> Option<u32> {
if bus_width == 0 || bus_width > 8 {
return None;
}
let bits_per_cycle = 8 / bus_width;
if bits_per_cycle == 0 {
return None;
}
let dummy_byte = dummy_cycle / bits_per_cycle;
Some(((dummy_byte & 0x3) << 6) | (((dummy_byte & 0x4) >> 2) << 14))
} |
|
CS index used without bounds checking: Arrays are sized
Then the code accesses: self.spi_data.cmd_mode[cs] // Panics if cs >= 5
self.spi_data.decode_addr[cs] // Panics if cs >= 5Fix: Change validation to fn select_cs(&mut self, cs: usize) -> Result<(), SpiError> {
if cs >= self.spi_config.max_cs || cs >= ASPEED_MAX_CS {
return Err(SpiError::CsSelectFailed(cs));
}
self.current_cs = cs;
Ok(())
} |
|
Recommendation: Split into separate files:
|
|
Location: pub static mut GPIO_ORI_VAL: [u32; 4] = [0; 4];This is a data race hazard. Access is through Recommendation: Use |
|
These will panic unconditionally if executed:
Fix: Return fn transfer_in_place(&mut self, _buffer: &mut [u8]) -> Result<(), SpiError> {
Err(SpiError::Other("transfer_in_place not supported"))
} |
|
the current SpiController: pub struct SpiController<'a> { |
No description provided.