From d80174d7c3fe36f139c639d6a820cc4cbb88ddf9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 15 Sep 2015 20:45:37 +0100 Subject: [PATCH] stmhal: Use polling, not DMA, for 1 byte SPI transfers. There is an issue sending 1 byte on the SPI bus using DMA, but it only occurs when the transmit is done for the first time after initialising the SPI and DMA peripherals. All other cases (sending 2 or more bytes, doing send_recv, doing recv first) work okay. We sidestep this issue by using polling (not DMA) for all 1 byte transfers. This is fine because a 1 byte transfer can't be interrupted and doesn't need the benefits of DMA (and using polling for this case is more efficient). Resolves #1456. --- stmhal/spi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/stmhal/spi.c b/stmhal/spi.c index b1aacfd0b7..864463df2d 100644 --- a/stmhal/spi.c +++ b/stmhal/spi.c @@ -476,8 +476,11 @@ STATIC mp_obj_t pyb_spi_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_ pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data); // send the data + // Note: there seems to be a problem sending 1 byte using DMA the first + // time directly after the SPI/DMA is initialised. The cause of this is + // unknown but we sidestep the issue by using polling for 1 byte transfer. HAL_StatusTypeDef status; - if (query_irq() == IRQ_STATE_DISABLED) { + if (bufinfo.len == 1 || query_irq() == IRQ_STATE_DISABLED) { status = HAL_SPI_Transmit(self->spi, bufinfo.buf, bufinfo.len, args[1].u_int); } else { DMA_HandleTypeDef tx_dma; @@ -528,7 +531,7 @@ STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_ // receive the data HAL_StatusTypeDef status; - if (query_irq() == IRQ_STATE_DISABLED) { + if (vstr.len == 1 || query_irq() == IRQ_STATE_DISABLED) { status = HAL_SPI_Receive(self->spi, (uint8_t*)vstr.buf, vstr.len, args[1].u_int); } else { DMA_HandleTypeDef tx_dma, rx_dma; @@ -625,7 +628,7 @@ STATIC mp_obj_t pyb_spi_send_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp // send and receive the data HAL_StatusTypeDef status; - if (query_irq() == IRQ_STATE_DISABLED) { + if (bufinfo_send.len == 1 || query_irq() == IRQ_STATE_DISABLED) { status = HAL_SPI_TransmitReceive(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len, args[2].u_int); } else { DMA_HandleTypeDef tx_dma, rx_dma;