cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 Interface with FSMC and DMA

ginnikhanna27
Associate II
Posted on March 21, 2012 at 12:56

Hi,

I have to read a 15 bit parallel data coming from a camera sensor and one bit as a request signal which tells whether the micrcontroller should initiate memory transfer or not.

Does FSMC has any trigger signal within itself so that I dont want to use any external interrupt or timer to trigger the transfer ?

Please help me out.
34 REPLIES 34
alok472
Associate II
Posted on March 28, 2012 at 03:47

Timer can initiate the DMA transactions from GPIO to Memory.

In Source Peripheral address : Put GPIO DR

In Destination : put RAM address..

ginnikhanna27
Associate II
Posted on March 29, 2012 at 10:37

Hi Alokm

Thanks alot for confirming that !

ginnikhanna27
Associate II
Posted on March 29, 2012 at 15:46

Hey!

I have a certain confusion regarding how does exactly the DMA transfer takes place from GPIO memory. How do I specify the address and tell the DMA that its a 15 bit parallel data which has to be tranferred at one got from GPIO to memory ?

Posted on March 29, 2012 at 16:02

You're going to specify it as a 16-bit transfer (ie HalfWord), and point it at the GPIOx->IDR

Presuming you aligned your GPIO input bits sensibly, ie GPIOx.0-14

Now if it spans too many bits you might need to do it as 32-bit and extract the bits you want later.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ginnikhanna27
Associate II
Posted on April 05, 2012 at 15:22

Is DMA transfer from GPIO pins to SRAM memory to memory transfer of data ?

Posted on April 05, 2012 at 17:41

Is DMA transfer from GPIO pins to SRAM memory to memory transfer of data ?

I'd kind of presume it could be a peripheral (non-increment) to memory (increment) transfer, but I haven't looked at all the busing/routing/muxing issues, and if you have a DMA controller on the right APB.

My understanding is peripheral-to-memory can be done via a direct routing, where as memory-to-memory will require more cycles, and an intermediate buffer, to complete the transaction in at least two steps/phases.

Either way, I don't suppose it would take more that 5-10 minutes to test/confirm what's workable, and what's not.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ginnikhanna27
Associate II
Posted on April 11, 2012 at 16:14

Hi

I was trying to congifure the DMA to transfer from GPIOE IDR register to SRAM. The transfer should be initiated with an external trigger on TIM2_CH2 i.e. DMA1 Channel 3 STream 6.  And here is what I wrote

// Configure Channel 2 for external signal//

        TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

        TIM_ICInitStructure.TIM_ICPolarity = 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(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);

        TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);

        TIM_ICInit(TIM2, &TIM_ICInitStructure);

        /* TIM enable counter */

        TIM_Cmd(TIM2, ENABLE);

        DMA_Cmd(DMA1_Stream6, ENABLE);

        TIM_DMACmd(TIM2,TIM_IT_Update,ENABLE);

        // Enable the Timer 2 Interrupt Request */

        TIM_ITConfig(TIM2, TIM_IT_Trigger, ENABLE);

        while(1)

        {

            GPIO_ResetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_14| GPIO_Pin_15);

            Delay(0xfffff);

        }

DMA_config()

{

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);

    DMA_DeInit(DMA1_Stream7);

    DMA_InitStructure.DMA_Channel = DMA_Channel_3;

    DMA_InitStructure.DMA_PeripheralBaseAddr = GPIOE_IDR_Address ;

    DMA_InitStructure.DMA_Memory0BaseAddr = SRC_Buffer;

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

    DMA_InitStructure.DMA_BufferSize = 8;

    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_Circular;

    DMA_InitStructure.DMA_Priority = DMA_Priority_High;

    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;

    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

    DMA_Init(DMA1_Stream6, &DMA_InitStructure)

}

there is no DMA initiation whenever the external trigger happens !

ginnikhanna27
Associate II
Posted on April 11, 2012 at 16:15

I even tried with TIM_DMA_Trigger instead of TIM_DMA_Update

Posted on April 11, 2012 at 17:45

TIM_DMACmd(TIM2,TIM_IT_Update,ENABLE); // ??

Surely that would be TIM_DMACmd(TIM2,TIM_DMA_Update,ENABLE);

or more realistically TIM_DMACmd(TIM2,TIM_DMA_CC2,ENABLE);

Since you want it to occur at the capture event, not when the timebase rolls-over, for which I don't see initialization code for. Or the pins or clocks.

The secondary issue would be whether each pulse triggers a single transfer, or the entire block.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ginnikhanna27
Associate II
Posted on April 12, 2012 at 10:28

I have to transfer a 15 bit data from GPIOE IDR to SRAM , only when there is an external trigger on TIM2 i.e. on PB3 pin. I have set the TIMER on Input capture mode. Moreover, an external trigger also initiates a DMA transfer on TIM2_CH2 DMA channel 3 stream 6. HEre is my compelte code :

/*

===============================================================================

*/

#ifdef __USE_CMSIS

#include ''stm32f4xx.h''

#endif

#define GPIOE_IDR_Address     0x40021000

#define GPIOE_ODR_Address     0x40021014

TIM_ICInitTypeDef  TIM_ICInitStructure;

DMA_InitTypeDef    DMA_InitStructure;

uint16_t SRC_Buffer[8] = {1,2,3,4,5,6,7,8};

void TIM_Config(void);

void GPIO_Config();

void Delay(__IO uint32_t nTime);

void TIM2_IRQHandler(void);

int main(void)

{

        GPIO_Config();

        TIM_Config();

        // Configure Channel 2 for external signal//

        TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

        TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

        TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

        TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

        TIM_ICInitStructure.TIM_ICFilter = 0x0;

        TIM_ICInit(TIM2, &TIM_ICInitStructure);

        TIM_Cmd(TIM2, ENABLE);

        TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);

        DMA_Cmd(DMA1_Stream6, ENABLE);

        TIM_DMACmd(TIM2,TIM_DMA_CC2,ENABLE);

        while(1)

                {

                    GPIO_ResetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_14| GPIO_Pin_15);

                    Delay(0xfffff);

                }

}

void TIM_Config(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;

    /* TIM2 clock enable */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    /* GPIOB clock enable */

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    /* TIM2 channel 2 pin (PB.3) configuration */

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_3;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Connect TIM pins to AF2 */

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_TIM2);

    /* Enable the TIM1 global Interrupt */

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);

    DMA_DeInit(DMA1_Stream6);

    DMA_InitStructure.DMA_Channel = DMA_Channel_3;

    DMA_InitStructure.DMA_PeripheralBaseAddr = GPIOE_IDR_Address ;

    DMA_InitStructure.DMA_Memory0BaseAddr = SRC_Buffer;

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

    DMA_InitStructure.DMA_BufferSize = 8;

    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_Circular;

    DMA_InitStructure.DMA_Priority = DMA_Priority_High;

    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;

    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

    DMA_Init(DMA1_Stream6, &DMA_InitStructure);

}

void GPIO_Config()

{

        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

        /* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_14| GPIO_Pin_15;

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;

        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

        GPIO_Init(GPIOD, &GPIO_InitStructure);

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1| GPIO_Pin_2| GPIO_Pin_3|GPIO_Pin_4| GPIO_Pin_5| GPIO_Pin_6|GPIO_Pin_7;

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

        GPIO_Init(GPIOE, &GPIO_InitStructure);

}

void TIM2_IRQHandler(void)

{

        {

            GPIO_SetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_14| GPIO_Pin_15);

            Delay(0xfffff);

            TIM_ClearFlag(TIM2, TIM_IT_CC2);

        }

}

void Delay(__IO uint32_t nTime)

{

  while(nTime--)

  {

  }

}

The interrupt is working absolutely fine, but there is no DMA transfer !