Skip to content

Commit 975e6b2

Browse files
author
Jamie Smith
authored
Fix some DMA SPI issues with DMA IP v3 and/or word size > 8 bits (#332)
* Fix some DMA SPI issues with DMA IP v3 and/or word size > 8 bits * Fix typo * oops fix naming
1 parent de273ee commit 975e6b2

File tree

3 files changed

+75
-7
lines changed

3 files changed

+75
-7
lines changed

targets/TARGET_STM/TARGET_STM32WB/stm_dma_info.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static const DMALinkInfo SPITxDMALinks[] = {
3535
/// Mapping from SPI index to DMA link info for Rx
3636
static const DMALinkInfo SPIRxDMALinks[] = {
3737
{1, 2, DMA_REQUEST_SPI1_RX},
38-
#ifdef SPI4
38+
#ifdef SPI2
3939
{1, 4, DMA_REQUEST_SPI2_RX}
4040
#endif
4141
};

targets/TARGET_STM/stm_dma_utils.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -684,11 +684,11 @@ DMA_HandleTypeDef *stm_init_dma_link(const DMALinkInfo *dmaLink, uint32_t direct
684684
if(direction == DMA_PERIPH_TO_MEMORY || direction == DMA_MEMORY_TO_MEMORY)
685685
{
686686
// Destination is memory
687-
dmaHandle->Init.DestInc = memInc ? DMA_SINC_INCREMENTED : DMA_SINC_FIXED;
687+
dmaHandle->Init.DestInc = memInc ? DMA_DINC_INCREMENTED : DMA_DINC_FIXED;
688688

689689
switch(memDataAlignment) {
690690
case 4:
691-
dmaHandle->Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
691+
dmaHandle->Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
692692
break;
693693
case 2:
694694
dmaHandle->Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;
@@ -702,11 +702,11 @@ DMA_HandleTypeDef *stm_init_dma_link(const DMALinkInfo *dmaLink, uint32_t direct
702702
}
703703
else {
704704
// Destination is a peripheral
705-
dmaHandle->Init.DestInc = periphInc ? DMA_SINC_INCREMENTED : DMA_SINC_FIXED;
705+
dmaHandle->Init.DestInc = periphInc ? DMA_DINC_INCREMENTED : DMA_DINC_FIXED;
706706

707707
switch(periphDataAlignment) {
708708
case 4:
709-
dmaHandle->Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
709+
dmaHandle->Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
710710
break;
711711
case 2:
712712
dmaHandle->Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;

targets/TARGET_STM/stm_spi_api.c

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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
15411597
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
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

Comments
 (0)