cancel
Showing results for 
Search instead for 
Did you mean: 

Refreshing DMA source address

firatparlak
Associate II
Posted on June 17, 2013 at 08:50

Hello,

I want to put the data from buffer(RAM) to the GPIO port(transmit) and from another GPIO port to the buffer(RAM)(receive) with the 2MHz clock. So I'm using DMA with input capture mode of the timer. The timer input is 2MHz. I succeeded transmit and receive operations which are explained above. The sync clock is 8KHz in the system. The interrupt occurs in the falling edge of the sync clock.(EXTI pin) After that, I want to refresh the DMAs' source address to the beginning address. But, there is a 1 us delay occurs and this a big problem for me. How can I refresh DMA or how can I restart DMA in the external interrupt routine? I'm waiting for your kindly helps.

void EXTI0_IRQHandler(void)//firat - 8 KHz Frame Sync
{ 
// if(EXTI_GetITStatus(EXTI_Line0) != RESET)
// {
//EXTI_ClearITPendingBit(EXTI_Line0);
EXTI->PR = EXTI_Line0; 
// DMA_InitStructure_.DMA_Memory0BaseAddr = (uint32_t)BPLDMATxBuff;
// BPLTx_DMA_STREAM->M0AR = DMA_InitStructure_.DMA_Memory0BaseAddr;
// DMA_InitStructure_.DMA_Memory0BaseAddr = (uint32_t)BPLDMARxBuff;
// BPLRx_DMA_STREAM->M0AR = DMA_InitStructure_.DMA_Memory0BaseAddr; 
DMA_Cmd(BPLTx_DMA_STREAM, ENABLE);
DMA_Cmd(BPLRx_DMA_STREAM, ENABLE);
TIM_DMACmd(TIM1,TIM_DMA_CC1 | TIM_DMA_CC2,ENABLE);
TIM_Cmd(TIM1, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
// }
}

#dma-double-buffer-memory-target #dma-restart #exti
5 REPLIES 5
jpeacock2399
Associate II
Posted on June 17, 2013 at 16:02

Thee are two ways to approach your problem.  The first would be to use circular mode DMA and enable the half complete transfer, assuming these are fixed length transfers.  Your DMA is 2 buffers deep, so that at the HT point you process the completed buffer while the second half is transferred.  This is your best option if using an F1 series part.

If you are using F2 to F4 series then you should look at double buffer mode in the DMA section of the Reference Manual.  It also works in circular mode but has two separate address pointers.

  Jack Peacock
firatparlak
Associate II
Posted on June 18, 2013 at 13:50

Thank you Jackfor the answer. But I realize that I should clarify the issue.

There are 2 different DMAs, 2 differentTimers and 2 different GPIO ports. One timer is used as input capture mode to trigger DMA_Tx, the other timer is used as input capture mode to trigger DMA_Rx. And there is an external 8Khz sync clock to synchronize the DMAs. The interrupt occurs in the falling edge of the sync clock(EXTI pin). After that, I want to refresh DMA's source address to the beginning address.

void BPLTx_Init(void)
{
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* TIM1 channel 2 pin (PA.8) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_TIM1);
//Enable the TIM1 global Interrupt
NVIC_InitStructure_.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure_.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure_.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure_.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure_);
RCC_AHB1PeriphClockCmd(BPLTx_DMA_CLK,ENABLE);//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
DMA_DeInit(BPLTx_DMA_STREAM); //DMA_DeInit(DMA2_Stream2);
DMA_InitStructure.DMA_Channel = BPLTx_DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = GPIOE_ODR_ADDRESS; //GPIOE_IDR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)BPLDMATxBuff; //(uint32_t)SRC_Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BPLDATASIZE; //256
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_Circular; //DMA_Mode_Normal; //
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(BPLTx_DMA_STREAM, &DMA_InitStructure); //DMA_Init(DMA2_Stream2, &DMA_InitStructure);
// Configure Channel 1 for external signal//
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //TIM_ICPolarity_Falling; //
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
//External clock mode 1 configured//
TIM_ETRClockMode1Config(TIM1, TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted , 0x00); //TIM_ExtTRGPolarity_Inverted
TIM_SelectInputTrigger(TIM1, TIM_TS_TI1FP1); //TIM_SelectInputTrigger(TIM8, TIM_TS_TI2FP2); //TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
TIM_ICInit(TIM1, &TIM_ICInitStructure); //TIM_ICInit(TIM3, &TIM_ICInitStructure); 
TIM_DMACmd(TIM1,TIM_DMA_CC1,ENABLE); //TIM_DMACmd(TIM1,TIM_DMA_CC2,ENABLE);
// DMA_Cmd(BPLTx_DMA_STREAM, ENABLE); //DMA_Cmd(DMA2_Stream2, ENABLE);
// /* TIM enable counter */
TIM_Cmd(TIM1, ENABLE);
// // Enable the Timer 1 Interrupt Request */
TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE); //Sync ile aktiflestiriliyor.
}
void BPLRx_Init(void) //Timer8 kullanildi.
{
/* TIM1 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOA clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* TIM8 channel 1 pin (PA.9) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Connect TIM pins to AF */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_TIM1);
//Enable the TIM1 global Interrupt
NVIC_InitStructure_.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure_.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure_.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure_.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure_);
RCC_AHB1PeriphClockCmd(BPLRx_DMA_CLK,ENABLE);
DMA_DeInit(BPLRx_DMA_STREAM);
DMA_InitStructure.DMA_Channel = BPLRx_DMA_CHANNEL;
DMA_InitStructure.DMA_PeripheralBaseAddr = GPIOD_IDR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)BPLDMARxBuff; //(uint32_t)SRC_Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = BPLDATASIZE; //256
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_Circular; //DMA_Mode_Normal; //
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(BPLRx_DMA_STREAM, &DMA_InitStructure);
// Configure Channel 2 for external signal//
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; //TIM_ICPolarity_Rising; //
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
//External clock mode 1 configured//
TIM_ETRClockMode1Config(TIM1, TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted , 0x00);// TIM_ExtTRGPolarity_Inverted
TIM_SelectInputTrigger(TIM1, TIM_TS_TI2FP2); // TIM_TS_TI2FP2
TIM_ICInit(TIM1, &TIM_ICInitStructure);
TIM_DMACmd(TIM1,TIM_DMA_CC2,ENABLE); 
// DMA_Cmd(BPLRx_DMA_STREAM, ENABLE);
// /* TIM enable counter */
TIM_Cmd(TIM1, ENABLE);
// Enable the Timer 1 Interrupt Request */
TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
}
void TIM1_CC_IRQHandler()
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC1 | TIM_IT_CC2);
}
void EXTI0_IRQHandler(void)//firat - 8 KHz Frame Sync
{ 
// if(EXTI_GetITStatus(EXTI_Line0) != RESET)
// {
EXTI_ClearITPendingBit(EXTI_Line0); 
// DMA_InitStructure_.DMA_Memory0BaseAddr = (uint32_t)BPLDMATxBuff;
// BPLTx_DMA_STREAM->M0AR = DMA_InitStructure_.DMA_Memory0BaseAddr;
// DMA_InitStructure_.DMA_Memory0BaseAddr = (uint32_t)BPLDMARxBuff;
// BPLRx_DMA_STREAM->M0AR = DMA_InitStructure_.DMA_Memory0BaseAddr; 
// BPLTx_DMA_STREAM->CR &= ~(uint32_t)DMA_SxCR_EN; // DMA_Cmd(BPLTx_DMA_STREAM, DISABLE);
// BPLRx_DMA_STREAM->CR &= ~(uint32_t)DMA_SxCR_EN;// DMA_Cmd(BPLRx_DMA_STREAM, DISABLE);
BPLTx_DMA_STREAM->CR |= (uint32_t)DMA_SxCR_EN; //DMA_Cmd(BPLTx_DMA_STREAM, ENABLE); // 
BPLRx_DMA_STREAM->CR |= (uint32_t)DMA_SxCR_EN; //DMA_Cmd(BPLRx_DMA_STREAM, ENABLE); //
// }
}

firatparlak
Associate II
Posted on June 18, 2013 at 14:17

How can I reconfigure DMA's memory address to the beginning address of the buffer while DMA is streaming?(DMA is enabled.)

Amel NASRI
ST Employee
Posted on June 18, 2013 at 18:07

DMA_MemoryInc_Disable?

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

firatparlak
Associate II
Posted on June 19, 2013 at 09:16

How can it be possible to transfer 256 byte data to the GPIO port with DMA_MemoryInc_Disable?

I want to transfer 256bytes data with 2.048Mhz clock and sync transfer operations with 8KHz clock. You can see clearly in the code which I wrote above.