2015-11-12 01:26 AM
This is a rather complex problem. I have an interrupt routine running under the systick handler with a period of 10mS. Within this I do 4096 reads of ADC3 via DMA2_Channel5, which works fine. Single shot mode
The problem comes when I have data coming in from USART2 via DMA1_Channel6. Occasionally DMA2 fails to complete the transfer, that is, it's counter decrements but does not get to zero.AFAIK I have set up the interrupts with systick having the highest priority, followed by DMA2 and then DMA1Any ideas as to what might be happening? #triage-nurse #stm322015-11-12 07:21 AM
If I add a 500uS delay at the end of my DMA setup the problem disappears - any ideas why?
_____________________________void DMA2_ADC3_Config(void){ DMA_InitTypeDef DMA_InitStructure; int numSamples; numSamples = sizeof( Receive.rawData ) / sizeof( Receive.rawData[0]); // Enable DMA2 clock RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); DMA_DeInit(DMA2_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &ADC3->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Receive.rawData; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = numSamples; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //Set for 16 bit DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA2_Channel5, &DMA_InitStructure); delayMicrosecondsT3(500);}_____________2015-11-12 09:56 AM
2015-11-13 03:49 AM
Hi - Not sure how to do that. I have set up the DMA to deliver 4096 samples as fast as the ADC can deliver them. I have now reduced the delay to 50uS and it still works perfectly. I would like to know why.
2015-11-18 03:35 AM
Can I please get some help on this. Having to put in a delay is causing serious problems elsewhere
2015-11-18 07:23 AM
Full code - which works, unless I remove the delay
void DMA2_Channel5_Config(void){ DMA_InitTypeDef DMA_InitStructure; int numSamples; numSamples = sizeof( Receive.rawData ) / sizeof( Receive.rawData[0]); // Enable DMA2 clock RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); DMA_DeInit(DMA2_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &ADC3->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Receive.rawData; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = numSamples; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //Set for 16 bit DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA2_Channel5, &DMA_InitStructure); DMA_Cmd( DMA2_Channel5, ENABLE ); delayMicrosecondsT3(50); //NOTE!!!!!!!!!!!!!!!!!!!!!!!!!!! No idea why this is needed, but without it the ADC/DMA sometimes never completes and the data collection hangs up} //****************************************************************************** // Set up ADC3 to do DMA conversions of sound reflections to memory // Note - Only some DMA and channels mapped to ADC numbers // DMA1_Ch1 -> ADC1 // DMA2_Ch1 -> ADC2 // DMA2_Ch2 -> ADC4 // DMA2_Ch3 -> ADC2 // DMA2_Ch4 -> ADC4 // DMA2_Ch5 -> ADC3 //****************************************************************************** void ADC3_Go( void ){ ADC_InitTypeDef ADC_InitStructure; int ADC_Sample_Time; RCC_ADCCLKConfig(RCC_ADC34PLLCLK_Div1); RCC_AHBPeriphClockCmd( RCC_AHBPeriph_ADC34, ENABLE ); ADC_StructInit( &ADC_InitStructure ); ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable; ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0; ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable; ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable; ADC_InitStructure.ADC_NbrOfRegChannel = 1; ADC_Init(ADC3, &ADC_InitStructure); ADC_Sample_Time = MachineState.ADC_Sample_Time; //Actual conversion time is 12.5 clock cycles + ADC_Sample_Time (usually 1.5 cycles) = 14 cycles ADC_RegularChannelConfig(ADC3, ADC_Channel_1, 1, ADC_Sample_Time); DMA2_Channel5_Config(); ADC_Cmd( ADC3, ENABLE ); //Enable ADC3 ADC_DMACmd( ADC3, ENABLE ); //Enable ADC3 DMA while( !ADC_GetFlagStatus( ADC3, ADC_FLAG_RDY ) ); // wait for ADRDY ADC_StartConversion( ADC3 ); // Start ADC3 Software Conversion }2015-11-18 07:37 AM
Do you call the function DMA2_ADC3_Config() repetitively?
I would enable the clock once and only once in main()Maybe you are trying to be safe by DMA_DeInit() but I doubt it is that useful.Using DMA with UART input is tricky. If there are errors, the DMA might not finish.there is a useful app note about using a timer to monitor activity on the UART pin which can provide a recovery mechanism when errors occur. Forgot the AN numberAnyway, AN4031 is a good read.2015-11-18 07:42 AM
I use DMA1 with the USART and DMA2 is reserved for ADC3
2015-11-18 08:20 AM
Full code...
Um, no. I'm not sure of the value of tearing down everything to restart the DMA, and if that is necessary, but the delay is indicative of a race condition, where you want to ensure this path loses. You'll need to look carefully at the order and sequence of things. Consider moving the clocks outside this level, and just what it takes to Init the DMA a second time around. You need to condense your failure condition into a complete/concise example, if I can't see a way to replicate/identify your issue in five minutes or less, I'm not going to even start looking. I think you need to figure out who's going to help you, and how much context and framework that's going to take.2015-11-19 07:03 AM
I have followed your suggestions and moved various initializations outside the loop. Still the same problem, which seems to stem from this code, in that when I do not use it there is no problem. This is set up during initialization and is not touched again.
void DMA_ConfigurationUSART2(void){ DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // USART2_RX DMA1 Channel 6 DMA_DeInit(DMA1_Channel6); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // Receive DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&PacketIn.buffer; DMA_InitStructure.DMA_BufferSize = sizeof( PacketIn.buffer ); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->RDR; 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_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_InitStructure.DMA_Priority = DMA_Priority_Low; DMA_Init(DMA1_Channel6, &DMA_InitStructure); // Enable the USART Rx DMA request USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE); // Enable DMA Stream Transfer Complete interrupt DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE); // Enable the DMA RX Stream DMA_Cmd(DMA1_Channel6, ENABLE);} void DMA1_Channel6_IRQHandler(void) //RX{ //Test on DMA Stream Transfer Complete interrupt if (DMA_GetITStatus(DMA1_IT_TC6)) { // Clear DMA Stream Transfer Complete interrupt pending bit DMA_ClearITPendingBit(DMA1_IT_TC6); if (PacketIn.rxFull == true) return; //Because we have not yet handled the other requests else PacketIn.rxFull = true; }}