mmcspi: add timeout on detecting edges & data

This commit is contained in:
Harry Ho 2021-12-18 00:33:00 +08:00
parent bc249c32df
commit 44171258f5
1 changed files with 30 additions and 19 deletions

View File

@ -1,4 +1,4 @@
use super::csr; use super::{csr, clock};
// Sayma MMC SSP1 configuration: // Sayma MMC SSP1 configuration:
// //
@ -46,44 +46,52 @@ fn cs_n() -> bool {
unsafe { csr::mmcspi::cs_n_in_read() == 1 } unsafe { csr::mmcspi::cs_n_in_read() == 1 }
} }
fn detect_cs_n_rise() { fn detect_cs_n_rise(timeout_us: u64) -> bool {
loop { let start = clock::get_us();
while clock::get_us() - start < timeout_us {
if cs_n() && unsafe { !PREV_CS_N } { if cs_n() && unsafe { !PREV_CS_N } {
unsafe { PREV_CS_N = true; } unsafe { PREV_CS_N = true; }
break return true;
} }
} }
false
} }
fn detect_cs_n_fall() { fn detect_cs_n_fall(timeout_us: u64) -> bool {
loop { let start = clock::get_us();
while clock::get_us() - start < timeout_us {
if !cs_n() && unsafe { PREV_CS_N } { if !cs_n() && unsafe { PREV_CS_N } {
unsafe { PREV_CS_N = false; } unsafe { PREV_CS_N = false; }
break return true;
} }
} }
false
} }
fn clk() -> bool { fn clk() -> bool {
unsafe { csr::mmcspi::clk_in_read() == 1 } unsafe { csr::mmcspi::clk_in_read() == 1 }
} }
fn detect_clk_rise() { fn detect_clk_rise(timeout_us: u64) -> bool {
loop { let start = clock::get_us();
while clock::get_us() - start < timeout_us {
if clk() && unsafe { !PREV_CLK } { if clk() && unsafe { !PREV_CLK } {
unsafe { PREV_CLK = true; } unsafe { PREV_CLK = true; }
break return true;
} }
} }
false
} }
fn detect_clk_fall() { fn detect_clk_fall(timeout_us: u64) -> bool {
loop { let start = clock::get_us();
while clock::get_us() - start < timeout_us {
if !clk() && unsafe { PREV_CLK } { if !clk() && unsafe { PREV_CLK } {
unsafe { PREV_CLK = false; } unsafe { PREV_CLK = false; }
break return true;
} }
} }
false
} }
fn mosi() -> u8 { fn mosi() -> u8 {
@ -100,7 +108,7 @@ fn read_continuous(buf: &mut [u8]) {
} }
// Wait until CS_n falling edge is detected, which indicates a new transaction // Wait until CS_n falling edge is detected, which indicates a new transaction
detect_cs_n_fall(); if !detect_cs_n_fall(1) { return }
for byte_ind in 0..buf.len() { for byte_ind in 0..buf.len() {
// Read bits from MSB to LSB // Read bits from MSB to LSB
@ -108,13 +116,13 @@ fn read_continuous(buf: &mut [u8]) {
// If CS_n goes high, return to indicate a complete SPI transaction // If CS_n goes high, return to indicate a complete SPI transaction
if cs_n() { break } if cs_n() { break }
// Detect and register CLK rising edge // Detect and register CLK rising edge
detect_clk_rise(); if !detect_clk_rise(1000) { return }
// Store the MOSI state as the current bit of the current byte // Store the MOSI state as the current bit of the current byte
if mosi() == 1 { if mosi() == 1 {
buf[byte_ind] |= 1 << bit_ind; buf[byte_ind] |= 1 << bit_ind;
} }
// Detect and register CLK falling edge // Detect and register CLK falling edge
detect_clk_fall(); if !detect_clk_fall(1000) { return }
} }
} }
} }
@ -152,13 +160,16 @@ pub fn read_eui48(buf: &mut [u8]) -> Result<(), ()> {
let mut spi_buf = [0_u8; 21]; let mut spi_buf = [0_u8; 21];
let mut is_broadcast = false; let mut is_broadcast = false;
// Loop to read a continuous byte transaction until the header correspond to the MMC broadcast format // Loop 10s to read a continuous byte transaction until the header correspond to the MMC broadcast format
while !is_broadcast { let start = clock::get_ms();
while !is_broadcast && clock::get_ms() - start <= 10_000 {
// Read 21 continguous bytes in a row // Read 21 continguous bytes in a row
read_continuous(&mut spi_buf); read_continuous(&mut spi_buf);
// Check the header // Check the header
is_broadcast = is_broadcast_header(&spi_buf[0..7]); is_broadcast = is_broadcast_header(&spi_buf[0..7]);
} }
// Return Err(()) if no broadcast header is detected
if !is_broadcast { return Err(()) }
// Truncate the header to get all data captured // Truncate the header to get all data captured
let data = &spi_buf[7..]; let data = &spi_buf[7..];
@ -181,7 +192,7 @@ pub fn read_eui48(buf: &mut [u8]) -> Result<(), ()> {
match (eui48_lo_ok, eui48_hi_ok) { match (eui48_lo_ok, eui48_hi_ok) {
(true, true) => Ok(()), (true, true) => Ok(()),
// This should never return Err() // This should never return Err(), unless the broadcast format has changed
_ => Err(()), _ => Err(()),
} }
} }