5 votos

DMA activado por temporizador utilizando la placa STM32F4-Discovery

Estoy tratando de activar el periférico DMA por el temporizador utilizando la placa STM32F4-Discovery, pero no parece funcionar.

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

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

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

¿Cómo consigo que el DMA funcione en el STM32F?

Edición 1: He adjuntado 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);
      }
 }

11voto

dchanson Puntos 29

La gran razón por la que el DMA no 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. Puedes ver como el GPIO C está conectado al sistema de memoria del chip en la tabla de abajo (encontrada en la sección Memory map del manual de referencia).

GPIO C memory map placement

Esto es importante porque los controladores DMA suelen implementarse teniendo en cuenta casos de uso específicos. En este caso, DMA1 se implementa teniendo en cuenta las transferencias de memoria a memoria. Se puede saber por los puntos de derivación de la matriz de bus (véase el gráfico siguiente, de la sección Arquitectura del sistema del Manual de referencia).

DMA memory taps

Los taps que faltan en AHB1 y AHB2 significan que, no importa cómo programes DMA1, en realidad no puede acceder a los datos GPIO, las conexiones físicas no están presentes. Sin embargo, DMA1 puede utilizar señales de los periféricos para activar transferencias. Lo que hace que el tema sea confuso.

Cambia a DMA2.

Parece que tuviste la idea correcta con el mapeo de una petición a un flujo, así que verás que, cuando cambies a DMA2, necesitarás elegir un nuevo temporizador y evento de disparo.

Espero que esto ayude.

0voto

jslav Puntos 1

Parece que no hay manera de utilizar ambos controladores DMA si necesito en una aplicación hacer

  1. activar el periférico DMA mediante el temporizador
  2. copiar mem a mem con DMA

porque DMA1 no está conectado físicamente al bus periférico el modo mem-to-mem no está implementado en STM32F4x5/STM32F4x7 RM0090 párrafo 8.3.6 Modos de origen, destino y transferencia 2 Sólo el controlador DMA2 puede realizar transferencias de memoria a memoria.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X