Skip to content

Commit 1668852

Browse files
Rework BMC read function.
We no longer store all the padding. Instead we poll the BMC until it gives us a valid header byte. Then we transfer the remainder of the message in one go. Should avoid the issue of the retry warning on the BMC slowing it down so much that the retries always failed.
1 parent 06be374 commit 1668852

File tree

1 file changed

+47
-49
lines changed

1 file changed

+47
-49
lines changed

src/main.rs

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,8 @@ impl Hardware {
426426
/// Give the device 2000ns before we take away CS.
427427
const CS_BUS_HOLD_CPU_CLOCKS: u32 = 2000 / Self::NS_PER_CLOCK_CYCLE;
428428

429-
/// Give the device 10ms to sort itself out when we do a retry.
430-
const SPI_RETRY_CPU_CLOCKS: u32 = 10_000_000 / Self::NS_PER_CLOCK_CYCLE;
429+
/// Give the device 100ms to sort itself out when we do a retry.
430+
const BMC_RETRY_CPU_CLOCKS: u32 = 100_000_000 / Self::NS_PER_CLOCK_CYCLE;
431431

432432
/// Give the BMC 6us to calculate its response
433433
const BMC_REQUEST_RESPONSE_DELAY_CLOCKS: u32 = 6_000 / Self::NS_PER_CLOCK_CYCLE;
@@ -616,7 +616,7 @@ impl Hardware {
616616
spi_bus: hal::Spi::new(spi).init(
617617
resets,
618618
clocks.peripheral_clock.freq(),
619-
2_000_000.Hz(),
619+
4_000_000.Hz(),
620620
&embedded_hal::spi::MODE_0,
621621
),
622622
delay,
@@ -833,9 +833,9 @@ impl Hardware {
833833
/// The number of bytes you want is set by the length of the `buffer` argument.
834834
///
835835
fn bmc_read_register(&mut self, register: u8, buffer: &mut [u8]) -> Result<(), ()> {
836-
const MAX_LATENCY: usize = 12;
836+
const MAX_LATENCY: usize = 128;
837837

838-
if (buffer.len() + MAX_LATENCY) > self.bmc_buffer.len() {
838+
if buffer.len() > self.bmc_buffer.len() {
839839
defmt::error!("Asked for too much data ({})", buffer.len());
840840
return Err(());
841841
}
@@ -851,64 +851,62 @@ impl Hardware {
851851
for byte in self.bmc_buffer.iter_mut() {
852852
*byte = 0xFF;
853853
}
854-
// Allow for up to eight bytes of padding (i.e. latency).
855-
let response_len = buffer.len() + MAX_LATENCY;
854+
let expected_response_len = buffer.len() + 2;
856855
defmt::debug!("req: {=[u8; 4]:02x}", req_bytes);
857-
self.with_bus_cs(0, |spi, buffer| {
856+
let mut latency = 0;
857+
self.with_bus_cs(0, |spi, borrowed_buffer| {
858858
// Send the request
859859
spi.write(&req_bytes).unwrap();
860-
cortex_m::asm::delay(Self::BMC_REQUEST_RESPONSE_DELAY_CLOCKS);
861-
// Get the response
862-
spi.transfer(&mut buffer[..response_len]).unwrap();
860+
for retry in 0..MAX_LATENCY {
861+
cortex_m::asm::delay(Self::BMC_REQUEST_RESPONSE_DELAY_CLOCKS);
862+
spi.transfer(&mut borrowed_buffer[0..=0]).unwrap();
863+
if neotron_bmc_protocol::ResponseResult::try_from(borrowed_buffer[0]).is_ok() {
864+
latency = retry;
865+
break;
866+
}
867+
}
868+
// Get the rest of the response now we know it's queued up.
869+
spi.transfer(&mut borrowed_buffer[1..expected_response_len])
870+
.unwrap();
863871
});
864-
// Trim the padding off the front
865-
let mut response_buffer = &self.bmc_buffer[..response_len];
866-
let mut latency = 0;
867-
while response_buffer.len() > 0
868-
&& neotron_bmc_protocol::ResponseResult::try_from(response_buffer[0]).is_err()
869-
{
870-
response_buffer = &response_buffer[1..];
871-
latency += 1;
872-
}
873-
defmt::debug!("res: {=[u8]:02x} ({})", response_buffer, latency);
874-
let expected_response_len = buffer.len() + 2;
872+
defmt::debug!(
873+
"res: {=[u8]:02x} ({})",
874+
self.bmc_buffer[0..expected_response_len],
875+
latency
876+
);
875877
// 8 bytes of data requested, plus one bytes of response code and one byte of CRC
876-
if response_buffer.len() >= expected_response_len {
877-
let response_portion = &response_buffer[0..expected_response_len];
878-
match neotron_bmc_protocol::Response::from_bytes(response_portion) {
879-
Ok(res) => {
880-
if res.result == neotron_bmc_protocol::ResponseResult::Ok
881-
&& res.data.len() == buffer.len()
882-
{
883-
buffer.copy_from_slice(res.data);
884-
return Ok(());
885-
} else {
886-
defmt::warn!(
887-
"Error reading {} bytes from {}: Error from BMC {:?} {=[u8]:x}",
888-
buffer.len(),
889-
register,
890-
res.result,
891-
response_portion
892-
);
893-
// No point retrying - we heardly them perfectly
894-
return Err(());
895-
}
896-
}
897-
Err(e) => {
878+
let response_portion = &self.bmc_buffer[0..expected_response_len];
879+
match neotron_bmc_protocol::Response::from_bytes(response_portion) {
880+
Ok(res) => {
881+
if res.result == neotron_bmc_protocol::ResponseResult::Ok
882+
&& res.data.len() == buffer.len()
883+
{
884+
buffer.copy_from_slice(res.data);
885+
return Ok(());
886+
} else {
898887
defmt::warn!(
899-
"Error reading {} bytes from {}: Decoding Error {:?} {=[u8]:x}",
888+
"Error reading {} bytes from {}: Error from BMC {:?} {=[u8]:x}",
900889
buffer.len(),
901890
register,
902-
e,
891+
res.result,
903892
response_portion
904893
);
894+
// No point retrying - we heardly them perfectly
895+
return Err(());
905896
}
906897
}
907-
} else {
908-
defmt::warn!("Short packet {=[u8]:x}", response_buffer);
898+
Err(e) => {
899+
defmt::warn!(
900+
"Error reading {} bytes from {}: Decoding Error {:?} {=[u8]:x}",
901+
buffer.len(),
902+
register,
903+
e,
904+
response_portion
905+
);
906+
}
909907
}
910908
// Wait a bit before we try again
911-
cortex_m::asm::delay(Self::SPI_RETRY_CPU_CLOCKS);
909+
cortex_m::asm::delay(Self::BMC_RETRY_CPU_CLOCKS);
912910
}
913911
panic!("Failed to talk to BMC after several retries.");
914912
}

0 commit comments

Comments
 (0)