AnsweredAssumed Answered

STM32F4DIS-CAM: DCIM to FLASH Memory using DMA Issue

Question asked by mauricio.joao on Jan 8, 2016
Latest reply on Jan 11, 2016 by mauricio.joao
Hi there,

I'm trying to use the STM32F4 Discovery kit (STM32F4Discovery + BB + CAM [OV9655]; without LCD) to take a 16-bits QVGA (320x240) shot and simply store it in a byte array. Assuming that all DMA and DCMI structures are properly set (which I believe that are; more on that later), a 153600 (320*240*2[=16bits]) byte array is needed, which clearly exceeds the 128K RAM size. With this in mind, and in order to validate my assumptions, I've run a couple of tests using smaller buffer sizes and byte arrays and successfully got partial "good" pictures: 320x120 when using a 76800 array and 320x140 with a 89600. As such, what I am now trying (and failing) to do is to use the FLASH memory to allocate the desired 153600 bytes and store the image data into it - although I am now able to r/w from/to the whole array using simple initialization/attribution (e.g.: frame_buffer[0] = 0x10), I can't get the DMA to write to it.

Please find the relevant code below.

001.#define DCMI_DR_ADDRESS 0x50050028
002.#define FRAME_BUFFER_SIZE 153600
003. 
004.__attribute__((__section__(".user_data"))) uint8_t frame_buffer[FRAME_BUFFER_SIZE] = {0};
005.// uint8_t frame_buffer[FRAME_BUFFER_SIZE/2] = {0}; // WORKS AS EXPECTED, ALTHOUGH JUST 1/2 IMAGE STORED
006. 
007.uint8_t DCMI_OV9655Config(void)
008.{
009.  I2C1_Config();
010. 
011.  I2C_GenerateSTART(I2C1, ENABLE);
012.  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
013.  I2C_GenerateSTOP(I2C1, ENABLE);
014.   
015.  if (DCMI_SingleRandomWrite(OV9655_DEVICE_WRITE_ADDRESS,0x12, 0x80))
016.    {
017.      return (0xFF);
018.    }
019.   
020.  DCMI_OV9655_QVGASizeSetup();
021. 
022.  DCMI_SingleRandomWrite(OV9655_DEVICE_WRITE_ADDRESS, OV9655_COM7, 0x63);
023.  DCMI_SingleRandomWrite(OV9655_DEVICE_WRITE_ADDRESS, OV9655_COM15, 0x10);
024. 
025.  DCMI_SingleRandomWrite(OV9655_DEVICE_WRITE_ADDRESS, OV9655_COM10, 0x08);
026. 
027.  DCMI_Config();
028. 
029.  return (0x00);
030.}
031. 
032.void I2C1_Config(void)
033.{
034.  GPIO_InitTypeDef GPIO_InitStructure;
035.  I2C_InitTypeDef  I2C_InitStruct;
036. 
037.  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
038. 
039.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
040. 
041.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
042.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);
043. 
044.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
045.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
046.  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
047.  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
048.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
049.  GPIO_Init(GPIOB, &GPIO_InitStructure);
050. 
051.  I2C_DeInit(I2C1);
052. 
053.  I2C_Cmd(I2C1, ENABLE);
054. 
055.  I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
056.  I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
057.  I2C_InitStruct.I2C_OwnAddress1 = 0xFE;
058.  I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
059.  I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
060.  I2C_InitStruct.I2C_ClockSpeed = 30000;
061. 
062.  I2C_Init(I2C1, &I2C_InitStruct);
063.}
064. 
065.void DCMI_Config(void)
066.{
067.  DCMI_InitTypeDef DCMI_InitStructure;
068.  GPIO_InitTypeDef GPIO_InitStructure;
069.  DMA_InitTypeDef  DMA_InitStructure;
070.   
071.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE |
072.             RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE);
073. 
074.  RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE);
075.   
076.  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI);
077.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
078.  GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_DCMI);
079.  GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_DCMI);
080.  GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_DCMI);
081.  GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_DCMI);
082.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_DCMI);
083.  GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_DCMI);
084.  GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_DCMI);
085.  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_DCMI);
086.  GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_DCMI);
087. 
088.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
089.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
090.  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
091.  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
092.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
093.  GPIO_Init(GPIOC, &GPIO_InitStructure);
094.   
095.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1
096.    | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
097.  GPIO_Init(GPIOE, &GPIO_InitStructure);
098.   
099.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
100.  GPIO_Init(GPIOB, &GPIO_InitStructure);
101.   
102.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6;
103.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
104.  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
105.  GPIO_Init(GPIOA, &GPIO_InitStructure);
106.   
107.  DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous;
108.  DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Hardware;
109.  DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Falling;
110.  DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_High;
111.  DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High;
112.  DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame;
113.  DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b;
114.   
115.  DCMI_Init(&DCMI_InitStructure);
116.   
117.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
118. 
119.  DMA_DeInit(DMA2_Stream1);
120.   
121.  DMA_InitStructure.DMA_Channel = DMA_Channel_1;
122.  DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
123.  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&frame_buffer;
124.  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
125.  DMA_InitStructure.DMA_BufferSize = FRAME_BUFFER_SIZE/4; // 320*240/WordSize
126.  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
127.  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
128.  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
129.  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
130.  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
131.  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
132.  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
133.  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
134.  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
135.  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
136.   
137.  DMA_Init(DMA2_Stream1, &DMA_InitStructure);
138.}
139. 
140.int main()
141.{
142.  DCMI_Control_IO_Init();
143. 
144.  if (DCMI_OV9655Config() == 0x0)
145.   {
146.    DMA_Cmd(DMA2_Stream1, ENABLE);
147.    DCMI_Cmd(ENABLE);
148.    DCMI_CaptureCmd(ENABLE);
149. 
150.    DCMI_CaptureCmd(DISABLE);
151.    for(i = 0; i < FRAME_BUFFER_SIZE; i++)
            {
152.          // frame_buffer[i] = i; // WORKS EVEN WHEN USING FLASH MEMORY. ALL 153600 BYTES BECOME SET AND READABLE
153.          printf("0x%02x\r\n", frame_buffer[i]);
154.    }
155.    DCMI_CaptureCmd(ENABLE);
156.   
157.    return 0;
158.}


LD script:

01.MEMORY
02.{
03.  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 896K
04.  DATA (rwx)      : ORIGIN = 0x080E0000, LENGTH = 128K  // ADDED
05.  RAM (rwx)       : ORIGIN = 0x20000000, LENGTH = 128K
06.  CCM (rwx)       : ORIGIN = 0x10000000, LENGTH = 64K
07.}
08. 
09.SECTIONS
10.{
11. 
12.  // ADDED SECTION
13.  .user_data :
14.  {
15.    . = ALIGN(4);
16.    *(.user_data)
17.    . = ALIGN(4);
18.  } >DATA
19. 
20.  ...

What am I missing here?

Thank you.

Best regards,
Joao Mauricio

Outcomes