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> { |
2. make sure GPIO_ORI_VA is safe with mutex 3. updated transfer_in_place() and flush() to return error code to avoid unexpected panic
4e2a712 to
22f573c
Compare
|
…. use a address strure
No description provided.