DMA activado por el temporizador utilizando la placa de descubrimiento STM32F4

2

Estoy intentando activar el periférico DMA mediante el temporizador utilizando la placa de descubrimiento STM32F4, pero no parece funcionar.

Quiero obtener el valor de un puerto (Puerto C) cada 5 ms y guardar el valor en la memoria en cierta dirección. Cuando el temporizador (TIM5) se desborda a los 5 ms, quiero que se active el DMA (DMA1 Stream6 Channel6).

Lo que he hecho: configurado el temporizador, el DMA, la interrupción del temporizador y también la interrupción DMA.

¿Debo respetar un cierto orden de las instrucciones? ¿Cómo hacer la conexión entre el DMA y el temporizador, aparte de usar el canal DMA específico?

¿Cómo puedo hacer que el DMA funcione en el STM32F?

Edición 1: adjunto el código

void Timer5_Setup(void)
{
TIM_TimeBaseInitTypeDef Timer5_InitStructure;       
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);        
Timer5_InitStructure.TIM_Prescaler = 1;         
Timer5_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;  
Timer5_InitStructure.TIM_Period = 0x48;     
Timer5_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  
TIM_TimeBaseInit(TIM5, &Timer5_InitStructure);  
TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);  
TIM_DMAConfig(TIM5, 0, TIM_DMABurstLength_1Transfer);
TIM_DMACmd(TIM5, TIM_DMA_Update | TIM_DMA_Trigger | TIM_DMA_COM, ENABLE);
TIM_SelectOutputTrigger(TIM5, TIM_TRGOSource_Update);
TIM_Cmd(TIM5, ENABLE);      
}


void DMA1_Config (void)
{
DMA_InitTypeDef  DMA_InitStructure;

DMA_DeInit(DMA1_Stream6);
DMA_StructInit(&DMA_InitStructure);

DMA_InitStructure.DMA_Channel = DMA_Channel_6;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(GPIOC->ODR);    
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) sdram_adr;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 2;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                        
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                                 
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                 
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                               
DMA_InitStructure.DMA_Priority = DMA_Priority_High;             
/*  
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
*/
DMA_Init(DMA1_Stream6, &DMA_InitStructure);


DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_TEIF6);
DMA_Cmd(DMA1_Stream6, ENABLE);

DMA_ITConfig(DMA1_Stream6, DMA_IT_TC | DMA_IT_HT, ENABLE);

TIM_DMAConfig(TIM5, TIM_DMABase_CR1 ,TIM_DMABurstLength_1Transfer);

TIM_Cmd(TIM5, ENABLE);
}

void TIM5_IRQHandler(void)
{
 if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) 
 {
    TIM_ClearITPendingBit(TIM5, TIM_IT_Update);     

    /*code related to app */        
 }
} 


void DMA1_Stream6_IRQHandler (void)
{
      if(DMA_GetITStatus(DMA1_Stream6, DMA_FLAG_TCIF6))
      {
      DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);
      }
 }
    
pregunta DragonflyN

1 respuesta

5

La gran razón por la que el DMA no se está transfiriendo es que en realidad no está conectado al periférico.

En la mayoría de las implementaciones de Cortex que he visto, hay varios buses de memoria. La implementación ST no es diferente. Puede ver cómo GPIO C está conectado al sistema de memoria del chip en la siguiente tabla (que se encuentra en la sección Mapa de memoria del manual de referencia).

LarazónqueesimportanteesqueloscontroladoresDMAgeneralmenteseimplementanteniendoencuentaloscasosdeusoespecíficos.Enestecaso,DMA1seimplementateniendoencuentalastransferenciasdememoriaamemoria.Puedesaberlodebidoalospuntosdecontactodelamatrizdebus(consulteelgráficoacontinuación,enlasecciónArquitecturadelsistemadelManualdereferencia).

Los grifos que faltan en AHB1 y AHB2 significan que, sin importar cómo programe DMA1, en realidad no puede acceder a los datos de GPIO, las conexiones físicas no están presentes. DMA1 puede, sin embargo, usar señales de los periféricos para desencadenar transferencias. Lo que hace que el problema sea confuso.

Cambia a DMA2.

Parece que tuvo la idea correcta de asignar una solicitud a un flujo, por lo que verá que cuando cambie a DMA2, deberá elegir un nuevo temporizador y un evento de activación.

Espero que esto ayude.

    
respondido por el pgvoorhees

Lea otras preguntas en las etiquetas