Para mi aplicación, tengo un DAC que se comunica con un STM32F4 a través de I2S. Del lado del microcontrolador, las informaciones se envían al DAC a través de un flujo DMA, con un búfer circular. En una interrupción externa, me gustaría pausar el DMA, cambiar algunos parámetros de sonido y luego reanudar el flujo de DMA.
Mi rutina de interrupción es básicamente así:
void HAL_GPIO_EXTI_Callback(uint16_t pin)
{
if(pin == GPIO_PIN_13)
{
HAL_I2S_DMAPause(&hi2s2);
changeSound(&sound);
HAL_I2S_DMAResume(&hi2s2);
}
}
Y tengo 2 rutinas de interrupción activadas en DMA TxHalf/TxCplt que llenan cada mitad de mi búfer DMA con el sonido. ( EDITAR : durante mi investigación también aprendí que hay un "modo de doble búfer" que permite hacer eso con algunas ventajas, pero eso está fuera de tema).
Lo que quiero evitar es transferir algunas muestras restantes del sonido anterior después de mi interrupción Exti. Entonces, mi idea era llenar todo el búfer después de cambiar el sonido y luego restablecer el puntero de memoria del flujo DMA al comienzo de mi búfer.
Se vería algo así:
void HAL_GPIO_EXTI_Callback(uint16_t pin)
{
if(pin == GPIO_PIN_13)
{
HAL_I2S_DMAPause(&hi2s2);
changeSound(&sound);
fillBuffer( address_of_1st_half, &sound);
fillBuffer( address_of_2nd_half, &sound);
*reset_DMA(&hi2s2)*; <==== this is the function I'm looking for
HAL_I2S_DMAResume(&hi2s2);
}
}
nb: como puede ver, estoy usando los controladores HAL de CubeMX
He buscado en la hoja de datos de HAL para tal función, pero no he encontrado ninguna.
Lo único que se acerca a eso es usar DMAStop() y luego Transmit_DMA() nuevamente. Pero me temo que llevaría demasiado tiempo...
Si alguien tiene una idea, ¡me encantaría escucharla!
Gracias
Ok, es posible que no haya encontrado una forma de restablecer el puntero DMA sin deshabilitar la transmisión (todavía), pero encontré más información y una forma de evitar el problema.
La última solución se vería así:
void HAL_GPIO_EXTI_Callback(uint16_t pin)
{
if(pin == GPIO_PIN_13)
{
changeSound(&sound);
while(DMA1_Stream4->NDTR >= 1);
HAL_I2S_DMAPause(&hi2s2);
fillBuf(&buf, &sound);
HAL_I2S_DMAResume(&hi2s2);
}
}
Todavía no lo he probado, así que no puedo estar seguro de si funciona o no, actualizaré esta respuesta tan pronto como lo haga.
Fuentes: