ST意法半导体
直播中

张国厚

7年用户 1389经验值
私信 关注
[问答]

为什么FMC总线总是将外部SDRAM操作复制到另一个地址位置上呢?

我通过 FMC 总线将 STM32F469 与外部 SDRAM (Alliance AS4C16M16MSA-6BIN) 一起使用。STM32F469 和 AS4C16M16MSA-6BIN 均在 1.8V 下运行。FMC 总线配置有 13 个地址引脚和 16 个数据引脚,如下所示:
  • hsdram1.Instance = FMC_SDRAM_DEVICE;
  • /* hsdram1.Init */
  • hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
  • hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
  • hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
  • hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
  • 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_DISABLE;
  • hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
  • /* Timing configuration for 75 MHz of SDRAM clock frequency () */
  • SdramTiming.LoadToActiveDelay = 2;
  • SdramTiming.ExitSelfRefreshDelay = 7;
  • SdramTiming.SelfRefreshTime = 4;
  • SdramTiming.RowCycleDelay = 7;
  • SdramTiming.WriteRecoveryTime = 2;
  • SdramTiming.RPDelay = 2;
  • SdramTiming.RCDDelay = 2;
而SDRAM配置为:
  • __IO uint32_t tmpmrd = 0;
  • /* Step 1: Configure a clock configuration enable command */
  • Command.CommandMode      = FMC_SDRAM_CMD_CLK_ENABLE;
  • Command.CommandTarget     = FMC_SDRAM_CMD_TARGET_BANK1;
  • Command.AutoRefreshNumber   = 1;
  • Command.ModeRegisterDefinition = 0;
  • /* Send the command */
  • HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
  • /* Step 2: Insert 100 us minimum delay */
  • /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
  • HAL_Delay(1);
  • /* Step 3: Configure a PALL (precharge all) command */
  • Command.CommandMode      = FMC_SDRAM_CMD_PALL;
  • Command.CommandTarget     = FMC_SDRAM_CMD_TARGET_BANK1;
  • Command.AutoRefreshNumber   = 1;
  • Command.ModeRegisterDefinition = 0;
  • /* Send the command */
  • HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
  • /* Step 4: Configure an Auto Refresh command */
  • Command.CommandMode      = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  • Command.CommandTarget     = FMC_SDRAM_CMD_TARGET_BANK1;
  • Command.AutoRefreshNumber   = 4;
  • Command.ModeRegisterDefinition = 0;
  • /* Send the command */
  • HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
  • /* Step 5: Program the external memory mode register */
  • tmpmrd = (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;
  • Command.CommandMode      = FMC_SDRAM_CMD_LOAD_MODE;
  • Command.CommandTarget     = FMC_SDRAM_CMD_TARGET_BANK1;
  • Command.AutoRefreshNumber   = 1;
  • Command.ModeRegisterDefinition = tmpmrd;
  • /* Send the command */
  • HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
  • /* Step 6: Set the refresh rate counter */
  • /* Set the device refresh rate */
  • HAL_SDRAM_ProgramRefreshRate(&hsdram1, RefreshCount);
我正在 SDRAM 上运行地址总线测试。
  • datum *
  • BSP_SDRAM_MemTestAddressBus(volatile datum * baseAddress, uint32_t nBytes)
  • {
  •         uint32_t addressMask = (nBytes/sizeof(datum) - 1);
  •         uint32_t offset;
  •         uint32_t testoffset;
  •         datum pattern                 = (datum) 0xAAAAAAA;
  •         datum antipattern         = (datum) 0x55555555;
  •         /*
  •          * Write the default pattern at each of power-of-two offsets
  •          * */
  •         for (offset = 1; (offset & addressMask) != 0; offset ++)
  •         {
  •                  *(__IO uint32_t*) (SDRAM_DEVICE_ADDR + 4*offset) = pattern;
  •         }
  •         /*
  •          * Write the default pattern at each of power-of-two offsets
  •          * */
  •         for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
  •         {
  •                 baseAddress[offset] = pattern;
  •         }
  •         /*
  •          * Check for address bits stuck high.
  •          * */
  •         testoffset = 2;
  •         baseAddress[testoffset] = antipattern;
  •         for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
  •         {
  •                 if (baseAddress[offset] != pattern)
  •                 {
  •                         return ((datum *) &baseAddress[offset]);
  •                 }
  •         }
  •         baseAddress[testoffset] = pattern;
  •         /*
  •          * Check for address bits stuck low or shorted.
  •          * */
  •         for (testoffset = 1; (testoffset & addressMask) !=0; testoffset <<=1)
  •         {
  •                 baseAddress[testoffset] = antipattern;
  •                         if (baseAddress[0] != pattern)
  •                         {
  •                                 return ((datum *) &baseAddress[testoffset]);
  •                         }
  •                 for (offset = 1; (offset & addressMask) != 0; offset <<=1)
  •                 {
  •                         if ((baseAddress[offset] != pattern) && (offset != testoffset))
  •                         {
  •                                 return ((datum *) &baseAddress[testoffset]);
  •                         }
  •                 }
  •                 baseAddress[testoffset] = pattern;
  •         }
  •         return (NULL);
  • }/* memTestAddressBus() */
问题是,当访问一个地址时,它总是将操作复制到另一个地址位置。内存读取如下:

我简单的写了0xAAAAAAA到0xC00000004这个位置,同时更新了0xC0000000C里面的数据。
关于这个问题有什么建议吗?提前致谢。

回帖(1)

顾鸿兰

2023-1-6 10:23:10
我们最终通过更换新的 SDRAM 解决了问题,看来故障很可能是由 BGA SDRAM 上的焊接不良引起的。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分