STM32 DCMI搬运数据到SDRAM造成STM32死机,反复重启问题

2019-07-20 12:02发布

本帖最后由 Gohome_soon 于 2017-9-13 17:30 编辑

最近使用STM32F429IGT6 +SDRAM画了一块板子,准备将DCMI采集的OV5640数据存在SDRAM中,但是发现,在搬运了一帧后,STM32不是卡死就是重启
STM32F429IGT6 我没有画外部晶振,而是使用内部HSI,时钟设置为168M

硬件连接:FMC_NBL[0:3]顺序接反了有没有影响呀?, 捕获.PNG

SDRAM型号是32位的 MT48LC4M32B2P-7 IT

OV5640使用的是原子的OV5640模块,输出图像设置为160*120

SDRAM初始化程序:
变量定义:[mw_shl_code=c,true]
u8 stream_data_buf[stream_buf_size] __attribute__((at(0XC0000000)));
u8 rgb565_buff[40*1024];[/mw_shl_code]
[mw_shl_code=c,true]void SDRAM_InitSequence(void)
{
  FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
  uint32_t tmpr = 0;

/* Step 3 --------------------------------------------------------------------*/
  /* Configure a clock configuration enable command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {

  }
  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);  
  
/* Step 4 --------------------------------------------------------------------*/
  /* Insert 100 ms delay */
  delay_ms(300);
   
/* Step 5 --------------------------------------------------------------------*/
  /* Configure a PALL (precharge all) command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */

  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {

  }
  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  
/* Step 6 --------------------------------------------------------------------*/
  /* Configure a Auto-Refresh command */
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 8;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  /* Wait until the SDRAM controller is ready */

  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {


  }
  /* Send the  first command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  
  /* Wait until the SDRAM controller is ready */

  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {


  }
  /* Send the second command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  
/* Step 7 --------------------------------------------------------------------*/
  /* Program the external memory mode register */
  tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1          |
                   SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
                   SDRAM_MODEREG_CAS_LATENCY_3           |
                   SDRAM_MODEREG_OPERATING_MODE_STANDARD |
                   SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
  
  /* Configure a load Mode register command*/
  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;

  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {
               
  }

  /* Send the command */
  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
  
/* Step 8 --------------------------------------------------------------------*/

  /* Set the refresh rate counter */
  /* (15.62 us x Freq) - 20 */
  /* Set the device refresh counter */
  FMC_SetRefreshCount(1200);

  /* Wait until the SDRAM controller is ready */
  while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
  {

  }
}

__IO uint32_t uwWriteReadStatus = 0;
void SDRAM_Init(void)
{
        
        
  FMC_SDRAMInitTypeDef  FMC_SDRAMInitStructure;
  FMC_SDRAMTimingInitTypeDef  FMC_SDRAMTimingInitStructure;

  /* GPIO configuration for FMC SDRAM bank */
  SDRAM_HW_Init();

  /* Enable FMC clock */
  RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);

        /* FMC Configuration ---------------------------------------------------------*/
        /* FMC SDRAM Bank configuration */   
  /* Timing configuration for 84 Mhz of SD clock frequency (168Mhz/2) */
        
  /* TMRD: 2 Clock cycles */
  FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay    = 2;   
        
  /* TXSR: min=70ns (7x11.90ns) */
  FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
        
  /* TRAS: min=42ns (4x11.11ns) max=120k (ns) */
  FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime      = 4;
        
  /* TRC:  min=70 (7x11.11ns) */        
  FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay        = 7;  
        
  /* TWR:  min=1+ 7ns (1+1x11.11ns) */
  FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime    = 2;      
        
  /* TRP:  20ns => 2x11.11ns */
  FMC_SDRAMTimingInitStructure.FMC_RPDelay              = 2;   
        
  /* TRCD: 20ns => 2x11.11ns */
  FMC_SDRAMTimingInitStructure.FMC_RCDDelay             = 2;
        
        //FMC_SDRAMInitStructure.FMC_InternalBankNumber        =        FMC_SDRAM_DEVICE;
        /* FMC SDRAM control configuration */
  FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank1_SDRAM;
        
  /* Row addressing: [7:0] */
  FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
        
  /* Column addressing: [11:0] */
  FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
        
  FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_32b;
  FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
  FMC_SDRAMInitStructure.FMC_CASLatency = FMC_CAS_Latency_3;
  FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
  FMC_SDRAMInitStructure.FMC_SDClockPeriod = SDCLOCK_PERIOD;  
  FMC_SDRAMInitStructure.FMC_ReadBurst = FMC_Read_Burst_Enable;
  FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1;
  FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
  
  /* FMC SDRAM bank initialization */
  FMC_SDRAMInit(&FMC_SDRAMInitStructure);
  /* FMC SDRAM device initialization sequence */
  SDRAM_InitSequence();

        /* Disable write protection */
  FMC_SDRAMWriteProtectionConfig(FMC_Bank1_SDRAM,DISABLE);
        
}[/mw_shl_code]OV5640和DCMI初始化,DCMI 使用原子的程序
[mw_shl_code=c,true]
while(OV5640_Init())//初始化OV5640
        {
                curr_times++;
                delay_ms(1);
                if(curr_times>=TIME_OUT)
                {               
                        showErrorInformation("Can't Find OV5640! ");
                        break;
                }               
        }
               
        if(curr_times<TIME_OUT)
        {
                        //        SHOW_OV5640_INFO("OV5640 Init 1 ");
                //delay_ms(100);
                curr_times=0;
                //自动对焦初始化
                OV5640_RGB565_Mode();        //RGB565模式        
                OV5640_Focus_Init();
                OV5640_Light_Mode(0);        //自动模式
                OV5640_Color_Saturation(3);// {MOD}彩饱和度0
                OV5640_Brightness(4);        //亮度0
                OV5640_Contrast(3);                //对比度0
                OV5640_Sharpness(33);        //自动锐度
                OV5640_Focus_Constant();//启动持续对焦
                OV5640_DCMI_Init();                        //DCMI配置
                DCMI_DMA_Init((uint32_t)rgb565_buff,0,160*120/2,0,1);//DCMI DMA配置
                OV5640_WR_Reg(0x3035,0X51);//降低输出帧率,否则可能抖动               
                OV5640_OutSize_Set(4,0,160,120);                //满屏缩放显示
                SHOW_OV5640_INFO("OV5640 Init End ");
                DCMI_Start();                         //启动传输
        //        SHOW_OV5640_INFO("DCMI START End ");
        }[/mw_shl_code]


首先DCMI将RGB565 数据传输到 stm32 内 RAM,然后再将数据拷贝到SDRAM中,循环运行,跑不了多久,stm32就会卡死,重启

while主循环
[mw_shl_code=c,true]while(1)
        {

                if(getSysTick()-last_times>=1000)
                {
                        curr_times++;
                        PGout(9)=!PGout(9);
                        printf("Time is %d s ",curr_times);
                        last_times=getSysTick();
                        //Flag_UsbRxEnd        |=        (1<<4);//数据准备完成开始发送                        
                }

                if((Flag_UsbRxEnd&(1<<4)))               
                {
                        
                        for(i=0;i<3840;i++)
                        {
                                stream_data_buf=rgb565_buff;
                        }

                        Flag_UsbRxEnd&=(~(1<<4));
                        printf("test_%d ",j++);
                        DCMI_Start();                         //启动传输

                }
[/mw_shl_code]

DCMI 传输完成中断
[mw_shl_code=c,true]//DCMI中断服务函数
void DCMI_IRQHandler(void)
{
        u32 i=0;
        if(DCMI->MISR&0X01)                //捕获到一帧图像
        {                        
                __disable_irq();
                DCMI->ICR|=1<<0;        //清除帧中断
                DCMI_Stop();
                for(i=0;i<0xFFFF;i++);
                Flag_UsbRxEnd        |=        (1<<4);//数据准备完成开始发送
                ov_frame++;
                printf("BMP end_%d ",Flag_UsbRxEnd);
                __enable_irq();
        }
}[/mw_shl_code]

当SDRAM自测时,它又是正常的
自测程序

[mw_shl_code=c,true]uint32_t sdram_checksum(void)
{
        uint32_t uwIndex = 0;
        uint32_t ubReaddata_32b = 0;  
        /* Write data to the SDRAM memory */
  for (uwIndex = 0; uwIndex < SDRAM_SIZE; uwIndex++)
  {
                while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
                {
                }        
    *(__IO uint32_t*) (SDRAM_BANK_ADDR  + 4*uwIndex) = (uint32_t)uwIndex+0x8B732167;               
  }
  
  /* Read back data from the SDRAM memory */
  for (uwIndex = 0; uwIndex < SDRAM_SIZE; uwIndex++)
  {
    ubReaddata_32b = *(__IO uint32_t*) (SDRAM_BANK_ADDR  + 4*uwIndex);
                        
                if (ubReaddata_32b != (uint32_t)uwIndex+0x8B732167)
    {
                        uwWriteReadStatus++;
    }
                ubReaddata_32b=0;
  }  
  
  /* Erase SDRAM memory */
  for (uwIndex = 0; uwIndex < SDRAM_SIZE; uwIndex++)
  {               
    *(__IO uint32_t*) (SDRAM_BANK_ADDR + 4*uwIndex) = (uint32_t)0x00000000;
               
  }
        
        return uwWriteReadStatus;
}[/mw_shl_code]

DCMI 和SDRAM以前使用STM32F429-Dis 一起用过的,换成自己画的板子就不行了哪,是应为我没有使用外部晶振吗
确实不知道怎么弄了,求众坛友们解惑呀






友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。