Skip to content

Commit

Permalink
spi: blackpill-f4: Implement spi_xfer_block for faster reads
Browse files Browse the repository at this point in the history
* Existing implementation has to walk up and down the function stack per byte,
  which is fine for commands and general poking
* 256-byte long page reads and writes can be accelerated because the length is known ahead of time
* Keep a byte in flight on stm32f1/f4 SPI (this is simpler than IRQ or DMA)
  • Loading branch information
ALTracer committed Oct 26, 2024
1 parent 85b4110 commit a23c853
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/include/platform_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ bool platform_spi_deinit(spi_bus_e bus);

bool platform_spi_chip_select(uint8_t device_select);
uint8_t platform_spi_xfer(spi_bus_e bus, uint8_t value);
void platform_spi_xfer_block(spi_bus_e bus, uint8_t *const data, size_t count);
#endif

#ifdef PLATFORM_IDENT_DYNAMIC
Expand Down
42 changes: 42 additions & 0 deletions src/platforms/common/blackpill-f4/blackpill-f4.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,48 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value)
}
}

void platform_spi_xfer_block(const spi_bus_e bus, uint8_t *const data, const size_t count)
{
uint32_t spi_base = OB_SPI;
switch (bus) {
case SPI_BUS_INTERNAL:
spi_base = OB_SPI;
break;
case SPI_BUS_EXTERNAL:
spi_base = EXT_SPI;
break;
default:
return;
}

#if 0
/* Put a byte on MOSI, wait entire transfer, grab the byte from MOSI into buffer, repeat. */
for (size_t i = 0; i < count; i++) {
uint8_t resp = spi_xfer(spi_base, data[i]);
data[i] = resp;
}
#else
CM_ATOMIC_CONTEXT();
/*
* Start the waveform by putting first MOSI byte into TXDR
* from which it falls immediately into the shadow register
* (pipelined polling version with inter-byte-gaps removed, no IRQ, no DMA)
*/
spi_write(spi_base, data[0]);
/*
* Put the next MOSI byte into TXDR,
* wait for previous byte from MOSI to appear in RXDR and copy it into buffer,
* repeat N-2 times
*/
for (size_t i = 0; i < count - 1; i++) {
spi_send(spi_base, data[i + 1]);
data[i] = spi_read(spi_base);
}
/* Once the last MOSI byte comes out, grab the last MISO byte */
data[count - 1] = spi_read(spi_base);
#endif
}

int platform_hwversion(void)
{
return 0;
Expand Down
8 changes: 8 additions & 0 deletions src/target/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,13 @@ void bmp_spi_read(const spi_bus_e bus, const uint8_t device, const uint16_t comm
bmp_spi_setup_xfer(bus, device, command, address);
/* Now read back the data that elicited */
uint8_t *const data = (uint8_t *const)buffer;
#if 0
for (size_t i = 0; i < length; ++i)
/* Do a write to read */
data[i] = platform_spi_xfer(bus, 0);
#else
platform_spi_xfer_block(bus, data, length);
#endif
/* Deselect the Flash */
platform_spi_chip_select(device);
}
Expand All @@ -81,9 +85,13 @@ void bmp_spi_write(const spi_bus_e bus, const uint8_t device, const uint16_t com
bmp_spi_setup_xfer(bus, device, command, address);
/* Now write out back the data requested */
const uint8_t *const data = (const uint8_t *)buffer;
#if 0
for (size_t i = 0; i < length; ++i)
/* Do a write to read */
platform_spi_xfer(bus, data[i]);
#else
platform_spi_xfer_block(bus, data, length);
#endif
/* Deselect the Flash */
platform_spi_chip_select(device);
}
Expand Down

0 comments on commit a23c853

Please sign in to comment.