@@ -853,9 +853,8 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
853
853
/* SPI slave implemtation in MBED does not support the 3 wires SPI.
854
854
* (e.g. when MISO is not connected). So we're forcing slave in
855
855
* 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.
857
857
*/
858
- debug ("3 wires SPI slave not supported - slave will only read\r\n" );
859
858
handle -> Init .Direction = SPI_DIRECTION_2LINES ;
860
859
}
861
860
@@ -1536,6 +1535,63 @@ typedef enum {
1536
1535
SPI_TRANSFER_TYPE_TXRX = 3 ,
1537
1536
} transfer_type_t ;
1538
1537
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
+ }
1539
1595
1540
1596
/// @returns True if DMA was used, false otherwise
1541
1597
static 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
1580
1636
}
1581
1637
1582
1638
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
+ }
1583
1651
}
1584
1652
1585
1653
obj -> spi .curr_transfer_uses_dma = useDMA ;
0 commit comments