我通过 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里面的数据。
关于这个问题有什么建议吗?提前致谢。