Skip to main content
ginnikhanna27
Associate II
March 21, 2012
Question

STM32 Interface with FSMC and DMA

  • March 21, 2012
  • 34 replies
  • 6429 views
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.
    This topic has been closed for replies.

    34 replies

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

    Hi Alokm

    Thanks alot for confirming that !

    ginnikhanna27
    Associate II
    March 29, 2012
    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 ?

    Tesla DeLorean
    Guru
    March 29, 2012
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    ginnikhanna27
    Associate II
    April 5, 2012
    Posted on April 05, 2012 at 15:22

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

    Tesla DeLorean
    Guru
    April 5, 2012
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    ginnikhanna27
    Associate II
    April 11, 2012
    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
    April 11, 2012
    Posted on April 11, 2012 at 16:15

    I even tried with TIM_DMA_Trigger instead of TIM_DMA_Update

    Tesla DeLorean
    Guru
    April 11, 2012
    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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
    ginnikhanna27
    Associate II
    April 12, 2012
    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 !

    ginnikhanna27
    Associate II
    April 12, 2012
    Posted on April 12, 2012 at 10:56

    Each pulse should initiate a 15 bit transfer at one go from GPIOE IDR to SRAM