Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

Commit 4cf226f

Browse files
committed
spi: blackpill-f4: Implement spi_xfer_block for faster reads
* 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)
1 parent 4c0c8c3 commit 4cf226f

3 files changed

Lines changed: 51 additions & 0 deletions

File tree

src/include/platform_support.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ bool platform_spi_deinit(spi_bus_e bus);
7777

7878
bool platform_spi_chip_select(uint8_t device_select);
7979
uint8_t platform_spi_xfer(spi_bus_e bus, uint8_t value);
80+
void platform_spi_xfer_block(spi_bus_e bus, uint8_t *const data, size_t count);
8081
#endif
8182

8283
#endif /* INCLUDE_PLATFORM_SUPPORT_H */

src/platforms/common/blackpill-f4/blackpill-f4.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,48 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value)
291291
}
292292
}
293293

294+
void platform_spi_xfer_block(const spi_bus_e bus, uint8_t *const data, const size_t count)
295+
{
296+
uint32_t spi_base = OB_SPI;
297+
switch (bus) {
298+
case SPI_BUS_INTERNAL:
299+
spi_base = OB_SPI;
300+
break;
301+
case SPI_BUS_EXTERNAL:
302+
spi_base = EXT_SPI;
303+
break;
304+
default:
305+
return;
306+
}
307+
308+
#if 0
309+
/* Put a byte on MOSI, wait entire transfer, grab the byte from MOSI into buffer, repeat. */
310+
for (size_t i = 0; i < count; i++) {
311+
uint8_t resp = spi_xfer(spi_base, data[i]);
312+
data[i] = resp;
313+
}
314+
#else
315+
CM_ATOMIC_CONTEXT();
316+
/*
317+
* Start the waveform by putting first MOSI byte into TXDR
318+
* from which it falls immediately into the shadow register
319+
* (pipelined polling version with inter-byte-gaps removed, no IRQ, no DMA)
320+
*/
321+
spi_write(spi_base, data[0]);
322+
/*
323+
* Put the next MOSI byte into TXDR,
324+
* wait for previous byte from MOSI to appear in RXDR and copy it into buffer,
325+
* repeat N-2 times
326+
*/
327+
for (size_t i = 0; i < count - 1; i++) {
328+
spi_send(spi_base, data[i + 1]);
329+
data[i] = spi_read(spi_base);
330+
}
331+
/* Once the last MOSI byte comes out, grab the last MISO byte */
332+
data[count - 1] = spi_read(spi_base);
333+
#endif
334+
}
335+
294336
int platform_hwversion(void)
295337
{
296338
return 0;

src/target/spi.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,13 @@ void bmp_spi_read(const spi_bus_e bus, const uint8_t device, const uint16_t comm
6767
bmp_spi_setup_xfer(bus, device, command, address);
6868
/* Now read back the data that elicited */
6969
uint8_t *const data = (uint8_t *const)buffer;
70+
#if 0
7071
for (size_t i = 0; i < length; ++i)
7172
/* Do a write to read */
7273
data[i] = platform_spi_xfer(bus, 0);
74+
#else
75+
platform_spi_xfer_block(bus, data, length);
76+
#endif
7377
/* Deselect the Flash */
7478
platform_spi_chip_select(device);
7579
}
@@ -81,9 +85,13 @@ void bmp_spi_write(const spi_bus_e bus, const uint8_t device, const uint16_t com
8185
bmp_spi_setup_xfer(bus, device, command, address);
8286
/* Now write out back the data requested */
8387
uint8_t *const data = (uint8_t *const)buffer;
88+
#if 0
8489
for (size_t i = 0; i < length; ++i)
8590
/* Do a write to read */
8691
platform_spi_xfer(bus, data[i]);
92+
#else
93+
platform_spi_xfer_block(bus, data, length);
94+
#endif
8795
/* Deselect the Flash */
8896
platform_spi_chip_select(device);
8997
}

0 commit comments

Comments
 (0)