写入STM32f7xxx中的SDRAM

问题描述 投票:0回答:1

我正在尝试将数据写入STM32CubeIde中STM32f746ZG板上的SDRAM。 这是代码:

  /* Enable the CPU Cache */
  CPU_CACHE_Enable();
  ...
  SDRAM_Timing.LoadToActiveDelay    = 2; //TMRD
  SDRAM_Timing.ExitSelfRefreshDelay = 7; //TXSR
  SDRAM_Timing.SelfRefreshTime      = 5; //TRAS
  SDRAM_Timing.RowCycleDelay        = 7; //TRC
  SDRAM_Timing.WriteRecoveryTime    = 3; //TWR
  SDRAM_Timing.RPDelay              = 3; //TRP
  SDRAM_Timing.RCDDelay             = 3; //TRCD

  hsdram.Init.SDBank             = FMC_SDRAM_BANK1;
  hsdram.Init.ColumnBitsNumber   = FMC_SDRAM_COLUMN_BITS_NUM_8;
  hsdram.Init.RowBitsNumber      = FMC_SDRAM_ROW_BITS_NUM_12;
  hsdram.Init.MemoryDataWidth    = FMC_SDRAM_MEM_BUS_WIDTH_16;
  hsdram.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
  hsdram.Init.CASLatency         = FMC_SDRAM_CAS_LATENCY_2;
  hsdram.Init.WriteProtection    = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  hsdram.Init.SDClockPeriod      = FMC_SDRAM_CLOCK_PERIOD_2;
  hsdram.Init.ReadBurst          = FMC_SDRAM_RBURST_ENABLE;
  hsdram.Init.ReadPipeDelay      = FMC_SDRAM_RPIPE_DELAY_0;

写入数据的代码片段:

 uint32_t aTxBuffer[BUFFER_SIZE];
 /* Fill the buffer to write */
  Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0);

  /* Write data to the SDRAM memory */
  for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)
  {
    *(__IO uint32_t*) (SDRAM_BANK_ADDR + WRITE_READ_ADDR + 4*uwIndex) = aTxBuffer[uwIndex];
  }

但是由于某种原因录音没有正确进行

也就是说,它写入了16个字节,但不写入接下来的8个字节,然后再次写入,然后不再写入。错误在哪里?我认为问题出在SDRAM_Timing上。附:请不要严厉批评我,这是我第一次使用 SDRAM

stm32 stm32cubeide stm32f7
1个回答
0
投票

您的 SDRAM 初始化序列不完整。初始化后,硬件还没有准备好使用。

SDRAM 初始化由两个阶段组成:

  1. 使用所有时序和突发配置初始化 MCU 的 SDRAM 处理外设(您已完成)。
  2. 在实际将 SDRAM IC 用于数据之前,通过发送一些命令来初始化 SDRAM IC 本身(您没有这样做)。

这是您需要的寄存器,直接来自 STM32F746 参考手册:

不久前,我为 STM32F746 Discovery Board 编写了我的小型裸机 2D 图形(原型)引擎(它从未去任何地方,但我在屏幕上浮动了半透明矩形),它使用 SDRAM 作为帧缓冲区。这是我测试过的代码中的一段。所有时间都是根据数据表手动计算的,没有使用“示例中的现成值”。我标记了你没有做的部分:

//GPIO is already configured
//MCU runs at 216MHz
//SDRAM clock is 108MHz

/*
 * Set up SDRAM Bank 1 control register
 *
 * Number of column address bits:   8
 * Number of row address bits:      12
 * Memory data bus width:           16
 * Number of internal banks:        4
 * CAS latency:                     2 Cycles
 * Write protection:                Write access allowed
 * SDRAM Clock Config:              Tsdclk = 2xThclk (108MHz @ 216MHz CPU clock)
 * Burst read:                      Single read requests NOT managed as bursts
 * Read Pipe:                       0 HCLK cycle delay
 *
 * */
FMC_Bank5_6->SDCR[0] = (0x00 << FMC_SDCR1_NC_Pos)
        | (0x01 << FMC_SDCR1_NR_Pos) | (0x01 << FMC_SDCR1_MWID_Pos)
        | (0x01 << FMC_SDCR1_NB_Pos) | (0x02 << FMC_SDCR1_CAS_Pos)
        | (0x00 << FMC_SDCR1_WP_Pos) | (0x02 << FMC_SDCR1_SDCLK_Pos)
        | (0x00 << FMC_SDCR1_RBURST_Pos) | (0x00 << FMC_SDCR1_RPIPE_Pos);

/*
 * Set up device timing
 *
 * Set Load Mode Register to Active Tmrd:   12ns (in no. of cycles, rounded up)
 * Exit Self-refresh delay Txsr:            70ns (in no. of cycles, rounded up)
 * Self-refresh time Tras:                  42ns (in no. of cycles, rounded up)
 * Row cycle delay Trc:                     6 Cycles for CAS latency 2, 10 cycles for CAS latency 3
 * Recovery delay Twr:                      Twr>=Tras-Trcd and Twr>=TRC-Trcd-Trp in cycles
 * Row precharge delay Trp:                 18ns (in no. of cycles, rounded up)
 * Row to column delay Trcd:                18ns (in no. of cycles, rounded up)
 *
 * */
FMC_Bank5_6->SDTR[0] = ((2U - 1U) << FMC_SDTR1_TMRD_Pos)        //2
| ((8U - 1U) << FMC_SDTR1_TXSR_Pos)     //8
        | ((5U - 1U) << FMC_SDTR1_TRAS_Pos)     //5
        | ((6U - 1U) << FMC_SDTR1_TRC_Pos)      //6
        | ((3U - 1U) << FMC_SDTR1_TWR_Pos)      //3
        | ((2U - 1U) << FMC_SDTR1_TRP_Pos)      //2
        | ((2U - 1U) << FMC_SDTR1_TRCD_Pos);    //2

// =====>>>>>>>>>>>>>>>> YOU DIDN'T DO THIS PART <<<<<<<<<<<<<<<<=====
/*
 * Initialize SDRAM IC via Command Mode register
 * Writing to MODE field issues commands
 * */
FMC_Bank5_6->SDCMR = (0x01 << FMC_SDCMR_CTB1_Pos)
        | ((1U - 1U) << FMC_SDCMR_NRFS_Pos)  //number of auto-refreshes
        | (0x01 << FMC_SDCMR_MODE_Pos); //start delivering clock to SDRAM bank 1 (SDCKE->HIGH)
//system_msdelay(1U);  //wait at least 100us after power up
for (uint32_t counter = 0x00; counter < 70000; counter++);

FMC_Bank5_6->SDCMR = (0x01 << FMC_SDCMR_CTB1_Pos)  //set bank 1
| ((1U - 1U) << FMC_SDCMR_NRFS_Pos)  //number of auto-refreshes
        | (0x02 << FMC_SDCMR_MODE_Pos);  //issue precharge all

FMC_Bank5_6->SDCMR = (0x01 << FMC_SDCMR_CTB1_Pos)  //set bank 1
| ((8U - 1U) << FMC_SDCMR_NRFS_Pos)  //number of auto-refreshes
        | (0x03 << FMC_SDCMR_MODE_Pos);  //issue auto-refreshes

/*
 * Create mode register value and load it into SDRAM mode register
 * Burst length:        1 (1 2 4 8 Page)
 * Burst type:          Sequential
 * Latency mode:        CAS latency 2
 * Operating mode:      Standard operation
 * Write burst mode:    Programmed burst length
 * Reserved:            Always 0
 *
 *   * */
uint32_t SDRAM_modeRegisterContent = (0x00 << 0x00) //[0:3]         Burst length
| (0x00 << 0x03)  //[3:1]       Burst type
        | (0x02 << 0x04)  //[4:3]       Latency mode
        | (0x00 << 0x07)  //[7:2]       Operating mode
        | (0x00 << 0x09)  //[9:1]       Write burst mode
        | (0x00 << 0x0A);  //[10:4]     Reserved

FMC_Bank5_6->SDCMR = (0x01 << FMC_SDCMR_CTB1_Pos)  //set bank 1
| (SDRAM_modeRegisterContent << FMC_SDCMR_MRD_Pos) //SDRAM mode register content
        | ((1U - 1U) << FMC_SDCMR_NRFS_Pos)  //number of auto-refreshes
        | (0x04 << FMC_SDCMR_MODE_Pos); //issue set mode register in the SDRAM;

//system_msdelay(1U);
for (uint32_t counter = 0x00; counter < 70000; counter++);
/*
 * SDRAM Refresh Timer
 * Refresh period:      64ms
 * Number of rows:      4096
 * Refresh rate:        64ms/4096rows = 15.62us
 * Count value:         15.62*108MHz - 20 = 1686.96 - 20 = ~1666
 *
 * RES Interrupt disable
 * Clear refresh error flag
 * */
uint32_t SDRAM_refreshCount = 1666U;  //1666U = 0x0682
FMC_Bank5_6->SDRTR = (0x00 << FMC_SDRTR_REIE_Pos) //RES interrupt enable OFF
| (SDRAM_refreshCount << FMC_SDRTR_COUNT_Pos) //load refresh count
        | (0x01 << FMC_SDRTR_CRE_Pos); //clear refresh error flag
//system_msdelay(1U);
for (uint32_t counter = 0x00; counter < 70000; counter++);

*(uint32_t*) (0xC0000000) = 0xBEEFCAFE; //test data, remember about endianness
© www.soinside.com 2019 - 2024. All rights reserved.