2017-03-25 1 views
0

Ich habe eine STM32F769I-EVAL konfiguriert, um 8 Bit parallele Daten basierend auf Code von ST AN4666 zu empfangen. Was ich erwarte, ist: Die Uhr von meinem Eingabegerät löst den Eingangserfassungs-DMA aus und schreibt Daten in den SDRAM, bis mein OC-Timer-Interrupt die Übertragung deaktiviert. An diesem Punkt kann ich die Daten im SDRAM manipulieren und an anderer Stelle übertragen. Nachdem die Hardware konfiguriert und die Eingabeaufzeichnung aktiviert wurde, erhalte ich jedoch einen DMA-Übertragungsfehler. Der Wert für den Fehlercode (6) in der Funktion HAL_DMA_IRQHandler zeigt, dass sowohl die FIFO- als auch die Transfer Error-Flags gesetzt sind. Nach meinem Verständnis der datasheet (siehe S. 261) sollte dies nicht möglich sein, ich nehme an, ich habe eine Einstellung irgendwo falsch konfiguriert, aber ich bin soweit nicht weiter wie weiter. Welche Schritte kann ich unternehmen, um dies zu lösen?STM32 DMA Transfer Fehler sowohl FIFO und Transfer Fehler Flags gesetzt

DMA-Konfiguration:

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) 
{ 
    GPIO_InitTypeDef GPIO_InitStruct; 
    static DMA_HandleTypeDef hdma_tim; 

    /* TIMx clock enable */ 
    TIMx_CLK_ENABLE(); 

    /* Enable DMA clock */ 
    DMAx_CLK_ENABLE(); 

    /* Enable TIM input GPIO clock */ 
    TIMx_CHy_GPIOCLK_ENABLE(); 

    /* Configure input of TIMx_CHy on AF */ 
    GPIO_InitStruct.Pin = TIMx_CHy_PIN; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 
    GPIO_InitStruct.Alternate = GPIO_AF_TIMx; 
    HAL_GPIO_Init(TIMx_CHy_PORT, &GPIO_InitStruct); 

    /* Set the parameters to be configured */ 
    hdma_tim.Init.Channel = DMA_CHANNEL; 
    hdma_tim.Init.Direction = DMA_PERIPH_TO_MEMORY; 
    hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE; 
    hdma_tim.Init.MemInc = DMA_MINC_ENABLE; 
    hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE ; /* Reading in GPIO PC[7:0]*/ 
    hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD ; 
    hdma_tim.Init.Mode = DMA_NORMAL; /* double memory buffer used */ 
    hdma_tim.Init.Priority = DMA_PRIORITY_HIGH; 
    hdma_tim.Init.FIFOMode = DMA_FIFOMODE_ENABLE; /* using FIFO mode since memory datasize=32bit and GPIO=8bits in our case */ 
    hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; /* flushing FIFO at each 32bit reception (4 data) */ 
    hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE; 
    hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE; 

    /* Set hdma_tim instance */ 
    hdma_tim.Instance = DMA_STREAM; 

    /* Link hdma_tim to hdma[CC1] */ 
    __HAL_LINKDMA(htim, hdma[TIMx_DMA_ID], hdma_tim); 

    /* Initialize TIMx DMA handle */ 
    HAL_DMA_Init(htim->hdma[TIMx_DMA_ID]); 

    /* NVIC configuration for TIMx output compare interrupt */ 
    HAL_NVIC_SetPriority(TIMx_IRQn, 0, 2); 
    HAL_NVIC_EnableIRQ(TIMx_IRQn); 

    /* Configure the NVIC for DMA        */ 
    /* NVIC configuration for DMA transfer complete interrupt */ 
    HAL_NVIC_SetPriority(TIMx_DMA_IRQn, 0, 0); 
    HAL_NVIC_EnableIRQ(TIMx_DMA_IRQn); 

} 

-Code von der Haupt:

/* Initialize SDRAM */ 
BSP_SDRAM_Init(); 

/* Configure the Data GPIO in input mode */ 
Data_GPIO_Config(); 

/* Set Timers instance */ 
TimHandle.Instance = TIMx; 

/* Initialize global Timer parameters */ 
TimHandle.Init.Period   = MAX_COUNTER; 
TimHandle.Init.Prescaler   = TIMx_PRESCALER - 1; 
TimHandle.Init.ClockDivision  = TIM_CLOCKDIVISION_DIV1; 
TimHandle.Init.CounterMode  = TIM_COUNTERMODE_UP; 
TimHandle.Init.RepetitionCounter = 0; 
if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK) 
{ 
    /* Initialization Error */ 
    Error_Handler(); 
} 

//Initialize Timer "OC" channel for OC mode 
sOConfig.OCMode  = TIM_OCMODE_TIMING/*TIM_OCMODE_TOGGLE*/; 
sOConfig.OCPolarity = TIM_OCPOLARITY_HIGH; 
sOConfig.Pulse  = NB_COUNTER_CYCLE; 
sOConfig.OCNPolarity = TIM_OCPOLARITY_HIGH; 
sOConfig.OCFastMode = TIM_OCFAST_DISABLE; 
sOConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET; 
sOConfig.OCIdleState = TIM_OCIDLESTATE_RESET; 
if (HAL_TIM_OC_ConfigChannel(&TimHandle, &sOConfig, TIMx_CHANNEL_OC) != HAL_OK) 
{ 
    //Configuration Error 
Error_Handler(); 
} 

/* Initialize Timer "IC" channel for IC mode  */ 
sICConfig.ICPolarity = CLK_LATCHING_DATA_EDGE; 
sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI; 
sICConfig.ICPrescaler = TIM_ICPSC_DIV1; 
sICConfig.ICFilter = TIM_IC_FILTER; /* filter the clock signal over/undershoot */ 
if (HAL_TIM_IC_ConfigChannel(&TimHandle, &sICConfig, TIMx_CHANNEL_IC) != HAL_OK) 
{ 
    /* Configuration Error */ 
    Error_Handler(); 
} 

/* Set the DMA memory0 conversion complete callback */ 
TimHandle.hdma[TIMx_DMA_ID]->XferCpltCallback = TransferComplete; 
/* Set the DMA memory1 conversion complete callback */ 
TimHandle.hdma[TIMx_DMA_ID]->XferM1CpltCallback = TransferComplete; 
/* Set the DMA error callback */ 
TimHandle.hdma[TIMx_DMA_ID]->XferErrorCallback = TransferError ; 

/* Update second memory address */ 
second_mem_address = (uint32_t)((SDRAM_BANK_ADDR + WRITE_READ_ADDR) + (DMA_MEM_BUFF_SIZE)); 

/* Start DMA multi buffer transfer */ 
if (HAL_DMAEx_MultiBufferStart_IT(TimHandle.hdma[TIMx_DMA_ID], GPIOx_IDR, (SDRAM_BANK_ADDR + WRITE_READ_ADDR), second_mem_address, DMA_MEM_BUFF_SIZE) != HAL_OK) 
{ 
    /* Transfer Error */ 
    Error_Handler(); 
} 

__HAL_TIM_ENABLE_DMA(&TimHandle, TIMx_DMA_CC); 

/* Enable the TIMx OC channel interrupt */ 
__HAL_TIM_ENABLE_IT(&TimHandle, TIMx_IT_OC); 
/* Enable the TIMX OC channel */ 
TIM_CCxChannelCmd(TimHandle.Instance, TIMx_CHANNEL_OC, TIM_CCx_ENABLE); 

/* Enable the TIMx IC channel */ 
TIM_CCxChannelCmd(TimHandle.Instance, TIMx_CHANNEL_IC, TIM_CCx_ENABLE); 

HAL_TIM_OC_Start(&TimHandle, TIMx_CHANNEL_OC); // enable counter 

/* processing while Timeout not reached */ 
while (timeout_flag == 0); 
+1

Die STlib HAL ist nur Bloatware ohne Nutzen. Verwenden Sie die direkte Registerprogrammierung. Auf diese Weise können Sie die Statusregister direkt überprüfen und überprüfen, was die Flags bedeuten. Verwenden Sie den Debugger für eine genauere Untersuchung. – Olaf

+0

Ändert STs HAL die Werte in den Statusregistern von dem, was sie wären, wenn ich meine eigenen Treiber schreiben würde? Ich kann die Statusregister im Debugger sehen und die oben erwähnten Fehlerflags werden im DMA_HISR-Interrupt-Statusregister gesetzt, aber ich weiß nicht, was ich sonst noch suchen sollte, um das Problem zu lösen, das ich sehe. – anOkCoder

+0

Ich arbeite nicht mit der HAL, da ich einen ersten Blick auf dieses Durcheinander hatte. Wie es behauptet, ein "Hardware ** Abstraction ** Layer" zu sein, würde ich annehmen, dass es tut. Es erschwert jedoch das Debugging und den Code. Wickeln Sie Ihre Hardware-Zugriffe stattdessen in einen semantischen Treiber ein (es ist sowieso eine gute Methode, HAL oder nicht). – Olaf

Antwort

1

Der Fehler wurde durch einen FIFO overrun Zustand verursacht, während die Daten zu empfangen. Erhöhen des FIFO-Schwellenwerts von 1/4 auf vollständig stoppt den Übertragungsfehler.

Der Cortex-M7 führt einen Daten- und Anweisungscache ein, der Probleme mit DMA-Übertragungen verursachen kann, aber ich konnte bestätigen, dass dies nicht der Fall war, weitere Informationen here.