|
自己做了块板子,MCU主控使用的是STM32F429IIT6,用到一个128MB的SDRAM—IS42S32400。现在在读取数据时候遇到了一个问题:SDRAM所有地址的32位数据中的第29位(从0开始)会随着读的过程而变化,从0跳变成1,造成读取错误。分别进行了32位与8位写入测试。
- 32位数据长度的写入测试中,往0xD000_0000~0xD100_0000依次写入地址的递增值(例如,往0xD0FF_FF00中写入0x00FF_FF00)。写入之后马上依次读出,与写入值进行比较。当二者不相等时输出此刻地址,做了几次实验,误码大致都发生在地址0xD029_0000~0XD040_0000之间,且一但发生了误码,则所有存储空间中的第29位全部变成1。
- 8位数据长度的读写测试中,往0xD000_0000~0xD100_00FF中分别写入0x00~0xFF,每写4个byte数据都会发生一次SDRAM所有存储空间中的第29位变成0,而后再变成1的过程。
个人怀疑是软件什么地方配置不对,可能跟SDRAM的刷新过程有关,附上SDRAM初始化代码:
- void MX_FMC_Init(void)
- {
- /* USER CODE BEGIN FMC_Init 0 */
- FMC_SDRAM_CommandTypeDef Command; // 控制指令
- __IO uint32_t tmpmrd=0;
- /* USER CODE END FMC_Init 0 */
- FMC_SDRAM_TimingTypeDef SdramTiming = {0};
- /* USER CODE BEGIN FMC_Init 1 */
- /* USER CODE END FMC_Init 1 */
- /** Perform the SDRAM1 memory initialization sequence
- */
- hsdram1.Instance = FMC_SDRAM_DEVICE;
- /* hsdram1.Init */
- hsdram1.Init.SDBank = FMC_SDRAM_BANK2;
- hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
- hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
- hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
- hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
- hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3;
- hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
- hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
- hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
- hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
- /* SdramTiming */
- SdramTiming.LoadToActiveDelay = 2;
- SdramTiming.ExitSelfRefreshDelay = 7;
- SdramTiming.SelfRefreshTime = 4;
- SdramTiming.RowCycleDelay = 7;
- SdramTiming.WriteRecoveryTime = 3;
- SdramTiming.RPDelay = 2;
- SdramTiming.RCDDelay = 2;
- if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
- {
- Error_Handler( );
- }
- /* USER CODE BEGIN FMC_Init 2 */
-
- /* Configure a clock configuration enable command */
- Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; // 开启SDRAM时钟
- Command.CommandTarget = FMC_COMMAND_TARGET_BANK; // 选择要控制的区域
- Command.AutoRefreshNumber = 1;
- Command.ModeRegisterDefinition = 0;
-
- HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT); // 发送控制指令
- SDRAM_delay(1); // 延时等待
-
- /* Configure a PALL (precharge all) command */
- Command.CommandMode = FMC_SDRAM_CMD_PALL; // 预充电命令
- Command.CommandTarget = FMC_COMMAND_TARGET_BANK; // 选择要控制的区域
- Command.AutoRefreshNumber = 1;
- Command.ModeRegisterDefinition = 0;
-
- HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT); // 发送控制指令
-
- /* Configure a Auto-Refresh command */
- Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; // 使用自动刷新
- Command.CommandTarget = FMC_COMMAND_TARGET_BANK; // 选择要控制的区域
- Command.AutoRefreshNumber = 8; // 自动刷新次数
- Command.ModeRegisterDefinition = 0;
-
- HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT); // 发送控制指令
-
- /* Program the external memory mode register */
- tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
- SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
- SDRAM_MODEREG_CAS_LATENCY_3 |
- SDRAM_MODEREG_OPERATING_MODE_STANDARD |
- SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
-
- Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE; // 加载模式寄存器命令
- Command.CommandTarget = FMC_COMMAND_TARGET_BANK; // 选择要控制的区域
- Command.AutoRefreshNumber = 1;
- Command.ModeRegisterDefinition = tmpmrd;
-
- HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT); // 发送控制指令
-
- hsdram1.Instance->SDRTR |= ((uint32_t)((1386)<< 1)); // 设置刷新计数器
- /* USER CODE END FMC_Init 2 */
- }
复制代码
ST-LINK调试的视频如下:
|
|