diff --git a/src/include/platform_support.h b/src/include/platform_support.h index 5e04ceb332b..fdb519bc33c 100644 --- a/src/include/platform_support.h +++ b/src/include/platform_support.h @@ -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, const uint8_t *tx_buf, uint8_t *rx_buf, size_t count); #endif #ifdef PLATFORM_IDENT_DYNAMIC diff --git a/src/platforms/common/blackpill-f4/blackpill-f4.c b/src/platforms/common/blackpill-f4/blackpill-f4.c index 1e26b875770..a4dc8585a2f 100644 --- a/src/platforms/common/blackpill-f4/blackpill-f4.c +++ b/src/platforms/common/blackpill-f4/blackpill-f4.c @@ -291,6 +291,52 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value) } } +/** + * @brief Run a full-duplex SPI transfer + * @param bus Which BMP SPI bus to use (internal/external) + * @param tx_buf Transmit data buffer of at least `count` size (nonempty) + * @param rx_buf Receive data buffer of same size (can alias, can be NULL) + * @param count Byte count for the transfer, and each buffer size. + */ +void platform_spi_xfer_block( + const spi_bus_e bus, const uint8_t *const tx_buf, uint8_t *const rx_buf, 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; + } + + 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, tx_buf[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, tx_buf[i + 1]); + uint8_t resp = spi_read(spi_base); + if (rx_buf) + rx_buf[i] = resp; + } + /* Once the last MOSI byte comes out, grab the last MISO byte */ + uint8_t resp = spi_read(spi_base); + if (rx_buf) + rx_buf[count - 1] = resp; +} + int platform_hwversion(void) { return 0; diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index e889527e872..392a128b117 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -519,6 +519,19 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value) return spi_xfer(bus == SPI_BUS_EXTERNAL ? EXT_SPI : AUX_SPI, value); } +void platform_spi_xfer_block( + const spi_bus_e bus, const uint8_t *const tx_buf, uint8_t *const rx_buf, const size_t count) +{ + const uint32_t spi_base = bus == SPI_BUS_EXTERNAL ? EXT_SPI : AUX_SPI; + + /* 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, tx_buf[i]); + if (rx_buf) + rx_buf[i] = resp; + } +} + void exti15_10_isr(void) { uint32_t usb_vbus_port; diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 4a423ff6039..71627b917c7 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -209,3 +209,13 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value) (void)bus; return value; } + +void platform_spi_xfer_block( + const spi_bus_e bus, const uint8_t *const tx_buf, uint8_t *const rx_buf, const size_t count) +{ + (void)bus; + (void)tx_buf; + (void)rx_buf; + (void)count; + return; +} diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index bff34040943..cff93831fd0 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -215,3 +215,13 @@ uint8_t platform_spi_xfer(const spi_bus_e bus, const uint8_t value) (void)bus; return value; } + +void platform_spi_xfer_block( + const spi_bus_e bus, const uint8_t *const tx_buf, uint8_t *const rx_buf, const size_t count) +{ + (void)bus; + (void)tx_buf; + (void)rx_buf; + (void)count; + return; +} diff --git a/src/target/spi.c b/src/target/spi.c index 872c68f4451..15e69c33a25 100644 --- a/src/target/spi.c +++ b/src/target/spi.c @@ -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, data, length); +#endif /* Deselect the Flash */ platform_spi_chip_select(device); } @@ -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, NULL, length); +#endif /* Deselect the Flash */ platform_spi_chip_select(device); }