Open maciejmatuszak opened 7 months ago
This is How I fixed it:
static uint16_t I2S_GetTransferBytes(i2s_dma_handle_t *handle, volatile i2s_transfer_t *transfer)
{
assert(transfer != NULL);
uint16_t transferBytes;
if (transfer->dataSize >( DMA_MAX_TRANSFER_COUNT*handle->bytesPerFrame))
{
transferBytes = DMA_MAX_TRANSFER_COUNT*handle->bytesPerFrame;
if ((transferBytes % 4U) != 0U)
{
transferBytes -= (transferBytes % 4U);
}
}
else
{
transferBytes = (uint16_t)transfer->dataSize;
}
return transferBytes;
}
Also I put assert in DMA_SetChannelXferConfig
static inline uint32_t DMA_SetChannelXferConfig(
bool reload, bool clrTrig, bool intA, bool intB, uint8_t width, uint8_t srcInc, uint8_t dstInc, uint32_t bytes)
{
assert(((uint32_t)bytes / (uint32_t)width - 1UL) < DMA_MAX_TRANSFER_COUNT);
return (DMA_CHANNEL_XFERCFG_CFGVALID_MASK | DMA_CHANNEL_XFERCFG_RELOAD(reload) |
DMA_CHANNEL_XFERCFG_CLRTRIG(clrTrig) | DMA_CHANNEL_XFERCFG_SETINTA(intA) |
DMA_CHANNEL_XFERCFG_SETINTB(intB) |
DMA_CHANNEL_XFERCFG_WIDTH((uint32_t)width == 4UL ? 2UL : ((uint32_t)width - 1UL)) |
DMA_CHANNEL_XFERCFG_SRCINC((uint32_t)srcInc == 4UL ? ((uint32_t)srcInc - 1UL) : (uint32_t)srcInc) |
DMA_CHANNEL_XFERCFG_DSTINC((uint32_t)dstInc == 4UL ? ((uint32_t)dstInc - 1UL) : (uint32_t)dstInc) |
DMA_CHANNEL_XFERCFG_XFERCOUNT((uint32_t)bytes / (uint32_t)width - 1UL));
}
Thanks for raising up the issue and suggest fix, I have forwarded the issue to internal developer, but the feedback maybe delayed, appreciate for your patience.
Describe the bug Submitting large I2S DMA Rx transfer using I2S_RxTransferReceiveDMA(...) splits the transfer into multiple DMA transfers. This happens if I2S_GetTransferBytes() reduce the size. I2S_GetTransferBytes calculates max single DMA transfer which is limited by hardware registers XFERCFGn:XFERCOUNT and XFERCFGn:WIDTH however the function I2S_GetTransferBytes uses:
Which assumes frame width of 4 bytes
(sizeof(uint32_t))
. This leads to I2S_GetTransferBytes() limiting it to 4096 bytes. The HW register XFERCFGn is set by DMA_SetChannelXferConfig() which tries to set the XFERCFGn:XFERCOUNT field to 4096/2=2048 which is bigger than the 10 bits the XFERCFGn:XFERCOUNT allows. As a result only half of the 4096 bytes buffer to be filled.To Reproduce
s_RxTransfer
is updated set thes_Buffer
to known values using memsets_Buffer
only half of it has data second half has the originalr
charactersExpected behavior The
s_Buffer
should be filled completlyScreenshots and console output
Additional context