Estoy usando un STM32L1 en una placa Nucleo-L152RE. Tengo dispositivos que controlo a través de una serie que funciona a velocidades bastante altas, por lo que estoy tratando de habilitar DMA en el USART. Con el siguiente código, puedo lanzar un Rx DMA, pero el segundo, que comencé desde el ISR nunca se completa:
void uart_receive_dma() {
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = UART_PACKET_SIZE;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_Init(uart_rx_dma_channel[handler->uart_index], &DMA_InitStructure);
/* RX */
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel5, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
}
void DMA1_Channel5_IRQHandler(void){
DMA_ClearITPendingBit(DMA1_IT_TC5);
uart_receive_dma();
}
int main(void) {
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
USART_Configuration();
/* First Rx, works and MA1_Channel5_IRQHandler gets called
uart_receive_dma();
while(1);
}
La primera transferencia de DMA funciona bien, así que supongo que no estoy limpiando algo antes de iniciar la segunda, pero no puedo averiguar de qué se trata.
Dependiendo de algunas condiciones externas, el código real no siempre reinicia la transferencia DMA desde DMA1_Channel5_IRQHandler sino que la reinicia desde otro lugar, por eso no puedo usar el DMA en modo circular.