Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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, const uint8_t *tx_buf, uint8_t *rx_buf, size_t count);
#endif

#ifdef PLATFORM_IDENT_DYNAMIC
Expand Down
46 changes: 46 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,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;
Expand Down
13 changes: 13 additions & 0 deletions src/platforms/native/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions src/platforms/stlink/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
10 changes: 10 additions & 0 deletions src/platforms/swlink/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're adding this new functionality, please just add it - if you want to preserve working with the old API then introduce a #define in the platform header that can be tested for here to switch to the new implementation. This will then also fix the builds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I felt like PLATFORM_HAS_SPI and PLATFORM_HAS_SPI_BLOCKWISE or so would be nice to add. The first macro would guard dummy impls in all but two platforms, the second macro would dispatch to calling a block xfer function instead of slow byte wise callchains.
But first I wanted to evaluate flash size increase from this feature.

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);
}
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, NULL, length);
#endif
/* Deselect the Flash */
platform_spi_chip_select(device);
}
Expand Down
Loading