Skip to main content
its
Associate III
November 1, 2012
Question

simultanous DMA filling and USART Tx from memory + camera output

  • November 1, 2012
  • 31 replies
  • 5851 views
Posted on November 01, 2012 at 07:56

hi:

I have interfaced camera with STM32F4 discovery. currently I am capturing the frame and after the first capture is complete, I disable Camera capture and start sending data from memory over USART2. it sequential. and works fine.

now , I want to send data over USART2 at the same time as after each DMA memory location filled by camera DATA.

Or i want to send the first frame data from DMA0 buffer while at the same time the next frame data will be filling to DMA1 buffer.(in double buffer mode)

is it possible.  and how>? any hint....

#dcmi-dma-camera #dma #usart #dcmi #wait-for-you--clive1-!-!-!
This topic has been closed for replies.

31 replies

Tesla DeLorean
Guru
November 1, 2012
Posted on November 01, 2012 at 14:29

There is no flow control between the DMA streams, so you can't set an out bound transfer against data you haven't yet received. Technically you can, but it's prone to data corruption, ie missing/losing.

Exchange regions of memory that the DMA Tx and Rx operations are using, or keep a list of regions/buffers which you pass off to each task as one completes.
Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
its
itsAuthor
Associate III
November 2, 2012
Posted on November 02, 2012 at 06:30

thanks.

         if i have u array of 20 charecters name string[20]. and I want to transfer only 20 bytes of that array,

1-how can i do that?

currently I have managed to transfer data of string[] through DMA over Usart TX , but it continues to transfer data from memory even after 20 bytes....and stops after transmitting large chunk of data! I am curious about

2-how DMA control this property?

3-how it knows when to stop transmitting DATA?

4-if it didn't know then why, after transmitting a large chunk of data form memory, it stops?

Thanks.
frankmeyer9
Associate III
November 2, 2012
Posted on November 02, 2012 at 10:05

currently I have managed to transfer data of string[] through DMA over Usart TX , but it continues to transfer data from memory even after 20 bytes....and stops after transmitting large chunk of data! I am curious about

 

Providing the involved source code would be helpful.

      if i have u array of 20 charecters name string[20]. and I want to transfer only 20 bytes of that array,

 

 

1-how can i do that?

 

  DMA_InitStructure.DMA_BufferSize = 20;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

3-how it knows when to stop transmitting DATA?

 

When all data items, according to your configuration, are transmitted.

The DMA may restart with the first item, if circular mode is configured. That would not make sense for feeding the UART, but is useful for the ADC.

4-if it didn't know then why, after transmitting a large chunk of data form memory, it stops?

 

You probably configured something else then 20, and might even end up in some fault handler. But that is hard to judge without the source code...

Tesla DeLorean
Guru
November 2, 2012
Posted on November 02, 2012 at 10:23

Definitely sounds like you're using Circular mode, DMA by itself just needs a length/size setting, and it should stop.

Don't use Circular mode, and use the TC (Terminal Count) interrupt to set up the next transfer, or not, as appropriate.
Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
its
itsAuthor
Associate III
November 2, 2012
Posted on November 02, 2012 at 10:47

very thanks. I just thought that I should upload some part of my code.

while(1) { DMA_Configuration(); DMA_Cmd(DMA1_Stream6, ENABLE); while (DMA_GetFlagStatus(DMA1_Stream6, DMA_FLAG_TCIF2) == RESET); DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_HTIF2 | DMA_FLAG_TCIF2); STM_EVAL_LEDOn(LED1); while(1); //USART_ClearFlag(USART2, USART_FLAG_TC); } ijust wanna tell after a large chunk of transmission , the transmission stops.  and LED1 didnt get ON. means the CODE stuck in between some where..!!!

 i will look upon the things u have mentioned
its
itsAuthor
Associate III
November 2, 2012
Posted on November 02, 2012 at 11:27

Here is complete main.c

 

 

char TxString[] = ''The quick brown fox jumps over the lazy dog\r\n'';

 #define USART2_DR_ADDRESS                ((uint32_t)USART2 + 0x04)

 

 

/**************************************************************************************/

 

void RCC_Configuration(void)

{

  /* Enable DMA clock */    

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);  

 

  /* Enable GPIO clock */

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

 

  /* Enable UART clock */

      RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

}

 

/**************************************************************************************/

 

void GPIO_Configuration(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

 

   

 

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

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

    GPIO_Init(GPIOA, &GPIO_InitStructure);  

 

   

}

 

/**************************************************************************************/

 

void USART_Configuration(void)

{

 // USART_InitTypeDef USART_InitStructure;

 USART_InitTypeDef USART_InitStructure;

 

  /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/

  /* USART configured as follow:

        - BaudRate = 115200 baud

        - Word Length = 8 Bits

        - One Stop Bit

        - No parity

        - Hardware flow control disabled (RTS and CTS signals)

        - Receive and transmit enabled

  */

 

 

   GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);

    

    USART_InitStructure.USART_BaudRate = 115200;

    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    USART_InitStructure.USART_StopBits = USART_StopBits_1;

    USART_InitStructure.USART_Parity = USART_Parity_No;

    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    USART_InitStructure.USART_Mode = USART_Mode_Tx;

    USART_Init(USART2, &USART_InitStructure);

   

 

 

  /* Enable the USART1 */

  USART_Cmd(USART2, ENABLE);

}

 

/**************************************************************************************/

 

void DMA_Configuration(void)

{

  DMA_InitTypeDef DMA_InitStructure1;

 

   DMA_DeInit(DMA1_Stream6);

   

 

  DMA_InitStructure1.DMA_PeripheralBaseAddr = USART2_DR_ADDRESS;

  DMA_InitStructure1.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure1.DMA_MemoryInc = DMA_MemoryInc_Enable;

  DMA_InitStructure1.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

  DMA_InitStructure1.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

  DMA_InitStructure1.DMA_Mode =  DMA_Mode_Circular;    //DMA_Mode_Normal;

  DMA_InitStructure1.DMA_Priority = DMA_Priority_VeryHigh;

  DMA_InitStructure1.DMA_FIFOMode =DMA_FIFOMode_Enable;

  DMA_InitStructure1.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

  DMA_InitStructure1.DMA_MemoryBurst = DMA_MemoryBurst_Single;

  DMA_InitStructure1.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

 

    

    DMA_InitStructure1.DMA_Channel = DMA_Channel_4 ;

    DMA_InitStructure1.DMA_DIR = DMA_DIR_MemoryToPeripheral;   

     

     

    DMA_InitStructure1.DMA_Memory0BaseAddr = (uint32_t)TxString;

    DMA_InitStructure1.DMA_BufferSize = 32 ;   //sizeof(TxString) - 1;

 

    DMA_Init(DMA1_Stream6, &DMA_InitStructure1);  

}

 

/**************************************************************************************/

 

int main(void)

{

  RCC_Configuration();

 

  GPIO_Configuration();

 

  USART_Configuration();

 

 

          USART_SendData(USART2,'K');  

    while (USART_GetFlagStatus( USART2, USART_FLAG_TC) != SET) ;

                         USART_ClearFlag(USART2, USART_FLAG_TC);

 

                     

      USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);

        

                        

                          

            STM_EVAL_LEDOff(LED1);              

  while(1)

  {            

    DMA_Configuration();

             

    DMA_Cmd(DMA1_Stream6, ENABLE);

                  

        

    while (DMA_GetFlagStatus(DMA1_Stream6, DMA_FLAG_TCIF2) == RESET);  

    DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_HTIF2  | DMA_FLAG_TCIF2);    

               

 

                  STM_EVAL_LEDOn(LED1);

                while(1);

               

                            

         //USART_ClearFlag(USART2, USART_FLAG_TC);  

          

  }

}

 

I have received the array content on hyper terminal but after that I got  a very large chunk of data, and the stops... but LED1 didnt get ON.

thanks

Tesla DeLorean
Guru
November 2, 2012
Posted on November 02, 2012 at 12:57

while(DMA_GetFlagStatus(DMA1_Stream6, DMA_FLAG_TCIF2) == RESET);

DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_HTIF2 | DMA_FLAG_TCIF2); Six not TWO

DMA_InitStructure1.DMA_Mode =  DMA_Mode_Circular;

Circular is repetitive.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
its
itsAuthor
Associate III
November 5, 2012
Posted on November 05, 2012 at 05:59

thanks,clive. my bad.

but I have make this correction, i got same result. My led1 did'nt blink aslo? can't understand that behavior, is that mean controller is stuck in while(getstatus....)?

I have also tried ur code u posted in ''DMA Memory To UART5''. but i got the same result. I got lot of data on my hyperterminal actually the same data as in my code. it always stops at the specif location (how i know that? because of same character appear every time)

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fDMA%20Memory%20To%20UART5&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=545

its
itsAuthor
Associate III
November 5, 2012
Posted on November 05, 2012 at 06:58

hi. thank God.

ahhhhhhhhhhhhhhhh

I had set DMA flow control as hardware flow control for camera in DMA.c, I set it to Memory flow control and voilaaaaaaaa... It runs perfect... thanks all for ur help..

now i am thinking what i have to do as camera use hardware control and uart use dma memory flow control?? will check it and update my status...

thanks again

its
itsAuthor
Associate III
November 5, 2012
Posted on November 05, 2012 at 10:47

hi,

initially i was using 128x128 image(32768 bytes of data). first i stored that in RAM through DMA then transmit it over USART. it works fine.

now i am shifted to 640x480 image. I have data stream of 614400 bytes coming from camera. the RAM did'nt support such a large buffer. image is comming at 60 FPS, i am taking only a snapshot at this rate. so it 614400 bytes data comes at very high rate to DMA.

how can i manage such a large and fast stream of data through DMA? I want to transmit data over USART at 115200 bps. is it even possible or not? hope u understand my query!

 in short i want to transmit data coming from camera, over to USART at 115200 bps. how is that possible?

Or i have to shift from usart to SPI for faster communication to avoid data over filling in DMA?

thanks