2025-06-08 1:22 AM - edited 2025-06-08 9:00 AM
I have set up a DMA on an I2S device with an STM32H503CBU6. The idea is, that the DMA runs continuously on a single bufferaddress (one word, containing the left and right channels for the external I2S-DAC). When the DMA transfer of that 1 word is complete it should start over again by itself.
At present the goal is not achieved with the following setup:
uint16_t ram_loc[2] = {0,0};
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_GPDMA1_Init();
MX_ICACHE_Init();
MX_I2C1_Init();
MX_I2S2_Init();
MX_TIM1_Init();
HAL_I2S_Transmit_DMA(&hi2s2, ram_loc,1); // since circular is configured,
// am I right that the DMA keeps alive itself?
/* USER CODE END 2 */
/* Infinite loop */
while (1)
{
// for testing, increment ram_loc (L+R) by one every 10ms
// which should produce a (sawtooth) ramp.
//
HAL_Delay(10);
ram_loc[0]++,ram_loc[1]++;
if(ram_loc[0] == 65535)
ram_loc[0]=ram_loc[1]=0;
}
}
Some things I'm not sure about: how is the DMA data organized. Since it is an I2S audio stream with L+R signals, I assume they are two words of 16bits, sent in one 32bit DMA chunk. Or is it 32bit data in a 32bit frame? BTW, what does "frame" actually stand for?
What is the "Port 0" that appears, when I choose "circular" mode in the DMA channel 4 setup?
I2S2_WS - PA3
I2S2_CK - PA5
I2S2_SDO - PB1
I don't see any data on PB1. Timing is there (48KHz on PA5, WS on PA3).
Solved! Go to Solution.
2025-06-10 1:13 AM
I got it running. I hadn't finished the necessary setup of the GPDMA.
Had to define a linked list with two nodes. And get some other parameters in the I2S interface (word length etc.) right. See attached IOC.
2025-06-08 6:22 AM
You should initialize ram_loc with nonzero data, and make it volatile.
volatile uint16_t ram_loc[2] = {0xAAAA, 0xAAAA};
Clock is there. Data is probably there as well. It's not being updated because the compiler is free to optimize it away.
2025-06-08 7:20 AM - edited 2025-06-08 7:26 AM
Would have been too nice, but:
volatile uint16_t ram_loc[2] = {0xAAAA, 0xAAAA};
../Core/Src/main.c: In function 'main':
../Core/Src/main.c:179:36: warning: passing argument 2 of 'HAL_I2S_Transmit_DMA' discards 'volatile' qualifier from pointer target type [-Wdiscarded-qualifiers]
179 | HAL_I2S_Transmit_DMA(&hi2s2, ram_loc,1); // since circular is configured,
| ^~~~~~~
And, thinking about it, the compiler shouldn't optimize a variable away, that is being passed to a function
and is being assigned (incremented) further down in the while loop in the code. Or am I wrong? And non-zero data? No, this can't be it.
Data is data, whether zero or non-zero, it's an initialization.
2025-06-08 7:48 AM
HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)ram_loc,1)
Cast it to the proper type to avoid the warning.
2025-06-08 8:49 AM - edited 2025-06-08 8:49 AM
@TDK wrote:
HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)ram_loc,1)
Cast it to the proper type to avoid the warning.
Did that, no change. Still no data. I'm wondering if it has to do sth. with circular and linked lists downstream in the DMA configuration in
HAL_I2S_Transmit_DMA
The fact that the timing can be seen at the I2S2 pins cannot be interpreted as the DMA being running, can it?
2025-06-08 9:13 AM - edited 2025-06-08 9:20 AM
I traced HAL_I2S_Transmit_DMA a bit. It runs into the following code:
/* Enable the Tx DMA Stream/Channel */
if ((hi2s->hdmatx->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
{
if (hi2s->hdmatx->LinkedListQueue != NULL)
{
/* Set DMA data size */
hi2s->hdmatx->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = hi2s->TxXferCount;
/* Set DMA source address */
hi2s->hdmatx->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)hi2s->pTxBuffPtr;
/* Set DMA destination address */
hi2s->hdmatx->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = (uint32_t)&hi2s->Instance->TXDR;
errorcode = HAL_DMAEx_List_Start_IT(hi2s->hdmatx);
}
I'm wondering about the
HAL_DMAEx_List_Start_IT(hi2s->hdmatx);
I cannot remember having enabled any interrupts.
Could it be I have to add a LINKEDLIST (under Utilities in the IOC)?
2025-06-10 1:13 AM