From 7f41f73f0f81e0ecbdb37d32ea7ad8cbc7468b06 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 22 Jun 2018 15:07:01 +1000 Subject: [PATCH] stm32/qspi: Don't require data reads and writes to be a multiple of 4. Prior to this patch the QSPI driver assumed that the length of all data reads and writes was a multiple of 4. This patch allows any length. Reads are optimised for speed by using 32-bit transfers when possible, but writes always use a byte transfer because they only use a single data IO line and are relatively slow. --- ports/stm32/qspi.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c index 97f055c099..a7cbbde014 100644 --- a/ports/stm32/qspi.c +++ b/ports/stm32/qspi.c @@ -181,16 +181,12 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, QUADSPI->AR = addr; - // Write out the data + // Write out the data 1 byte at a time while (len) { while (!(QUADSPI->SR & QUADSPI_SR_FTF)) { } - // TODO it seems that writes need to be 32-bit wide to start the xfer... - //*(volatile uint8_t*)QUADSPI->DR = *src++; - //--len; - QUADSPI->DR = *(uint32_t*)src; - src += 4; - len -= 4; + *(volatile uint8_t*)&QUADSPI->DR = *src++; + --len; } } @@ -253,13 +249,23 @@ STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, QUADSPI->ABR = 0; // alternate byte: disable continuous read mode QUADSPI->AR = addr; // addres to read from - // Read in the data - while (len) { - while (!(QUADSPI->SR & QUADSPI_SR_FTF)) { + // Read in the data 4 bytes at a time if dest is aligned + if (((uintptr_t)dest & 3) == 0) { + while (len >= 4) { + while (!(QUADSPI->SR & QUADSPI_SR_FTF)) { + } + *(uint32_t*)dest = QUADSPI->DR; + dest += 4; + len -= 4; } - *(uint32_t*)dest = QUADSPI->DR; - dest += 4; - len -= 4; + } + + // Read in remaining data 1 byte at a time + while (len) { + while (!((QUADSPI->SR >> QUADSPI_SR_FLEVEL_Pos) & 0x3f)) { + } + *dest++ = *(volatile uint8_t*)&QUADSPI->DR; + --len; } QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag