rp: Tidy up flash_put_get function

This commit is contained in:
James Turton 2022-09-19 15:35:20 +02:00 committed by Rachel Mant
parent a8c75ac4f4
commit c6f8fb507d
1 changed files with 16 additions and 15 deletions

View File

@ -684,37 +684,38 @@ static int rp_flash_was_aborted(target *const t)
// If rx_skip is nonzero, this many bytes will first be consumed from the FIFO, // If rx_skip is nonzero, this many bytes will first be consumed from the FIFO,
// before reading a further count bytes into *rx. // before reading a further count bytes into *rx.
// E.g. if you have written a command+address just before calling this function. // E.g. if you have written a command+address just before calling this function.
static void rp_flash_put_get(target *const t, const uint8_t *tx, uint8_t *rx, const size_t count, size_t rx_skip) static void rp_flash_put_get(
target *const t, const uint8_t *const tx, uint8_t *const rx, const size_t count, size_t rx_skip)
{ {
// Make sure there is never more data in flight than the depth of the RX // Make sure there is never more data in flight than the depth of the RX
// FIFO. Otherwise, when we are interrupted for long periods, hardware // FIFO. Otherwise, when we are interrupted for long periods, hardware
// will overflow the RX FIFO. // will overflow the RX FIFO.
const uint max_in_flight = 16 - 2; // account for data internal to SSI static const size_t max_in_flight = 16 - 2; // account for data internal to SSI
size_t tx_count = count; size_t tx_count = 0;
size_t rx_count = count; size_t rx_count = 0;
while (tx_count || rx_skip || rx_count) { while (tx_count < count || rx_count < count || rx_skip) {
// NB order of reads, for pessimism rather than optimism // NB order of reads, for pessimism rather than optimism
const uint32_t tx_level = target_mem_read32(t, RP_SSI_TXFLR); const uint32_t tx_level = target_mem_read32(t, RP_SSI_TXFLR);
const uint32_t rx_level = target_mem_read32(t, RP_SSI_RXFLR); const uint32_t rx_level = target_mem_read32(t, RP_SSI_RXFLR);
bool did_something = false; // Expect this to be folded into control flow, not register bool idle = true; // Expect this to be folded into control flow, not register
if (tx_count && tx_level + rx_level < max_in_flight) { if (tx_count < count && tx_level + rx_level < max_in_flight) {
target_mem_write32(t, RP_SSI_DR0, (uint32_t)(tx ? *tx++ : 0)); target_mem_write32(t, RP_SSI_DR0, (uint32_t)(tx ? tx[tx_count] : 0));
--tx_count; ++tx_count;
did_something = true; idle = false;
} }
if (rx_level) { if (rx_level) {
uint8_t rxbyte = target_mem_read32(t, RP_SSI_DR0); const uint8_t data = target_mem_read32(t, RP_SSI_DR0);
did_something = true;
if (rx_skip) if (rx_skip)
--rx_skip; --rx_skip;
else { else {
if (rx) if (rx)
*rx++ = rxbyte; rx[rx_count] = data;
--rx_count; ++rx_count;
} }
idle = false;
} }
// APB load costs 4 cycles, so only do it on idle loops (our budget is 48 cyc/byte) // APB load costs 4 cycles, so only do it on idle loops (our budget is 48 cyc/byte)
if (!did_something && rp_flash_was_aborted(t)) if (idle && rp_flash_was_aborted(t))
break; break;
} }
rp_spi_chip_select(t, RP_GPIO_QSPI_CS_DRIVE_HIGH); rp_spi_chip_select(t, RP_GPIO_QSPI_CS_DRIVE_HIGH);