@@ -853,9 +853,8 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
853853 /* SPI slave implemtation in MBED does not support the 3 wires SPI.
854854 * (e.g. when MISO is not connected). So we're forcing slave in
855855 * 2LINES mode. As MISO is not connected, slave will only read
856- * from master, and cannot write to it. Inform user.
856+ * from master, and cannot write to it.
857857 */
858- debug ("3 wires SPI slave not supported - slave will only read\r\n" );
859858 handle -> Init .Direction = SPI_DIRECTION_2LINES ;
860859 }
861860
@@ -1536,6 +1535,63 @@ typedef enum {
15361535 SPI_TRANSFER_TYPE_TXRX = 3 ,
15371536} transfer_type_t ;
15381537
1538+ /*
1539+ * Configure a DMA channel's transfer size to match the given SPI word size
1540+ */
1541+ static void configure_dma_transfer_size (const uint32_t spiDataSize , DMA_HandleTypeDef * const dmaChannel )
1542+ {
1543+ #if DMA_IP_VERSION_V3
1544+ uint32_t * const transferSizePtr1 = & dmaChannel -> Init .DestDataWidth ;
1545+ uint32_t * const transferSizePtr2 = & dmaChannel -> Init .SrcDataWidth ;
1546+ uint32_t neededSizeVal1 ;
1547+ uint32_t neededSizeVal2 ;
1548+
1549+ if (spiDataSize <= SPI_DATASIZE_8BIT )
1550+ {
1551+ neededSizeVal1 = DMA_DEST_DATAWIDTH_BYTE ;
1552+ neededSizeVal2 = DMA_SRC_DATAWIDTH_BYTE ;
1553+ }
1554+ else if (spiDataSize <= SPI_DATASIZE_16BIT )
1555+ {
1556+ neededSizeVal1 = DMA_DEST_DATAWIDTH_HALFWORD ;
1557+ neededSizeVal2 = DMA_SRC_DATAWIDTH_HALFWORD ;
1558+ }
1559+ else
1560+ {
1561+ neededSizeVal1 = DMA_DEST_DATAWIDTH_WORD ;
1562+ neededSizeVal2 = DMA_SRC_DATAWIDTH_WORD ;
1563+ }
1564+ #else
1565+ uint32_t * const transferSizePtr1 = & dmaChannel -> Init .PeriphDataAlignment ;
1566+ uint32_t * const transferSizePtr2 = & dmaChannel -> Init .MemDataAlignment ;
1567+ uint32_t neededSizeVal1 ;
1568+ uint32_t neededSizeVal2 ;
1569+
1570+ if (spiDataSize <= SPI_DATASIZE_8BIT )
1571+ {
1572+ neededSizeVal1 = DMA_PDATAALIGN_BYTE ;
1573+ neededSizeVal2 = DMA_MDATAALIGN_BYTE ;
1574+ }
1575+ else if (spiDataSize <= SPI_DATASIZE_16BIT )
1576+ {
1577+ neededSizeVal1 = DMA_PDATAALIGN_HALFWORD ;
1578+ neededSizeVal2 = DMA_MDATAALIGN_HALFWORD ;
1579+ }
1580+ else
1581+ {
1582+ neededSizeVal1 = DMA_PDATAALIGN_WORD ;
1583+ neededSizeVal2 = DMA_MDATAALIGN_WORD ;
1584+ }
1585+ #endif
1586+
1587+ // Check values and reinit DMA if needed
1588+ if (* transferSizePtr1 != neededSizeVal1 || * transferSizePtr2 != neededSizeVal2 )
1589+ {
1590+ * transferSizePtr1 = neededSizeVal1 ;
1591+ * transferSizePtr2 = neededSizeVal2 ;
1592+ HAL_DMA_Init (dmaChannel );
1593+ }
1594+ }
15391595
15401596/// @returns True if DMA was used, false otherwise
15411597static bool spi_master_start_asynch_transfer (spi_t * obj , transfer_type_t transfer_type , const void * tx , void * rx , size_t length , DMAUsage hint )
@@ -1580,6 +1636,18 @@ static bool spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfe
15801636 }
15811637
15821638 useDMA = true;
1639+
1640+ // Make sure that the DMA word size matches the SPI word size. Also check address alignment.
1641+ if (transfer_type == SPI_TRANSFER_TYPE_TXRX || transfer_type == SPI_TRANSFER_TYPE_TX )
1642+ {
1643+ MBED_ASSERT (((ptrdiff_t )tx ) % (1 << bitshift ) == 0 ); // <-- if you hit this assert you passed an unaligned pointer to an SPI async transfer
1644+ configure_dma_transfer_size (handle -> Init .DataSize , handle -> hdmatx );
1645+ }
1646+ if (transfer_type == SPI_TRANSFER_TYPE_TXRX || transfer_type == SPI_TRANSFER_TYPE_RX )
1647+ {
1648+ MBED_ASSERT (((ptrdiff_t )rx ) % (1 << bitshift ) == 0 ); // <-- if you hit this assert you passed an unaligned pointer to an SPI async transfer
1649+ configure_dma_transfer_size (handle -> Init .DataSize , handle -> hdmarx );
1650+ }
15831651 }
15841652
15851653 obj -> spi .curr_transfer_uses_dma = useDMA ;
0 commit comments