硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4292|回复: 8
收起左侧

两片 MT48LC32M16的SDRAM 操作读写问题 ?

[复制链接]

680

主题

3479

回帖

5544

积分

论坛元老

积分
5544
发表于 2016-10-24 11:26:48 | 显示全部楼层 |阅读模式
两片 MT48LC32M16的SDRAM 操作读写问题 ??? 描述如下:

#define SDRAM_BASE_ADDR            ((uint32_t)0xC0000000)     // CS0

1、按照 32位的读写,完全正常,

  {   // sdram 读写,按照32位进行测试, 使用指针进行操作 ok
    uint32_t  *ptrSdramAddr;
    ptrSdramAddr = (uint32_t *)SDRAM_BASE_ADDR;   //   吧地址转换为指针

    printf("\r\nSDRAM 测试 开始 ...");
    for(ii=0;ii<0x2000000;ii++)  // 128MByte   1024*1024*32*4/1024/4
    {
      *ptrSdramAddr  = ( __IO uint32_t )(SDRAM_BASE_ADDR + (ii * 4));  

      ptrSdramAddr ++;        // 每加一次表示是4个字节的地址数目
    }

    ptrSdramAddr = (uint32_t *)SDRAM_BASE_ADDR;   //   吧地址转换为指针
    printf("\r\nSDRAM 测试 开始读出数据进行校对 ......");
    for(ii=0;ii<0x2000000;ii++)  // 128MByte   1024*1024*32*4/1024/4
    {
      jj  = *ptrSdramAddr++;   

      if(jj != (SDRAM_BASE_ADDR +  (ii * 4) ) )
        printf("\r\nSDRAM 测试 读循环 出错");
      else
      {
        if(ii >= (0x2000000 - 1))
        {
          printf("\r\nSDRAM 测试 读循环次数 = 0x%X", ii + 1);
          printf("\r\nSDRAM 测试 读 地址 = 0x%X", SDRAM_BASE_ADDR + (ii * 4) + 4);
        }
      }
    }   
  }

2、按照 16位的读写,不正常

  {   // sdram 读写,按照16位进行测试, 使用指针进行操作
    uint16_t  *ptrSdramAddr;
    uint32_t  dattt;
    uint16_t  cc=0;
    ptrSdramAddr = (uint16_t *)SDRAM_BASE_ADDR;   //   吧地址转换为指针

    for(ii=0;ii<0x4000000;ii++)  // 128MByte   1024*1024*32*4/1024/4
    {
      *ptrSdramAddr  = cc;  

      ptrSdramAddr ++;        // 每加一次表示是2个字节的地址数目
      cc ++;
    }

    printf("\r\nSDRAM 测试 开始读出数据进行校对 ......");
    ptrSdramAddr = (uint16_t *)SDRAM_BASE_ADDR;   //   吧地址转换为指针

    cc = 0;
    for(ii=0;ii<0x4000000;ii++)  // 128MByte   1024*1024*32*4/1024/4
    {
      dattt  = *ptrSdramAddr;
      ptrSdramAddr ++;
      if(dattt != cc )
        printf("\r\nSDRAM 测试 读循环 出错");
      else
      {
        if(ii >= (0x4000000 - 1))
        {
          printf("\r\nSDRAM 测试 读循环次数 = 0x%X", ii + 1);
          printf("\r\nSDRAM 测试 读 地址 = 0x%X", SDRAM_BASE_ADDR + (ii * 2) + 2);
        }
      }
      cc ++;
    }   
  }


有谁知道这是为何吗 ????

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115653
QQ
发表于 2016-10-24 11:46:21 | 显示全部楼层
这个就是你上次说的,采用两个16位的组成32位的那个测试吗。
回复

使用道具 举报

680

主题

3479

回帖

5544

积分

论坛元老

积分
5544
 楼主| 发表于 2016-10-24 14:06:18 | 显示全部楼层

回 eric2013 的帖子

eric2013:这个就是你上次说的,采用两个16位的组成32位的那个测试吗。 (2016-10-24 11:46)
是的啊,目前测试 32位模式没有问题,就是16位、8位不行,但是 16/8位单独读写貌似又可以

配置如下:

  /* 两片 MT48LC32M16(数据宽度16位) 组合成为 一片 MT48LC32M32(即把两片16位的组合成32位宽的)*/
   void MX_FMC_Init(void)
{
  FMC_SDRAM_TimingTypeDef SdramTiming;
  hsdram1.Instance = FMC_SDRAM_DEVICE;                                //SDRAM在BANK5,6
  /* hsdram1.Init */
  hsdram1.Init.SDBank = FMC_SDRAM_BANK1;                              // SDRAM接在BANK5上
  hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_10;       // 列地址线数目
  hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;             // 行地址线数目
  hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;          // 数据宽度 32位
  hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;     // 一共4个BANK
  hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;                  // CAS为3
  hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;  // 写保护禁止
  hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;              // SDRAM时钟为HCLK/2
  hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;                   // 使能突发读
  hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;               // 定义在CAS个延时后在等待多少个HCLK时钟才读取数据


  /* SdramTiming */
  SdramTiming.LoadToActiveDelay = 2;      // TMDR 加载模式寄存器到激活时间的延迟为2个时钟周期
  SdramTiming.ExitSelfRefreshDelay = 6;   // TXSR 退出自刷新延迟为x个时钟周期
  SdramTiming.SelfRefreshTime = 4;        // TRAS 自刷新时间为x个时钟周期
  SdramTiming.RowCycleDelay = 6;          // TRC  行循环延迟为x个时钟周期
  SdramTiming.WriteRecoveryTime = 2;      // TWR  恢复延迟为x个时钟周期
  SdramTiming.RPDelay = 2;                // TRP  行预充电延迟为x个时钟周期
  SdramTiming.RCDDelay = 2;               // TRCD 行到列延迟为x个时钟周期

  if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
  {
    Error_Handler();
  }
  BSP_SDRAM_Initialization_Sequence( &hsdram1  );
}




#define SDRAM_TIMEOUT     ((uint32_t)0xFFFF)

#define SDRAM_MODEREG_BURST_LENGTH_1             ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2             ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4             ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8             ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2              ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3              ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((uint16_t)0x0200)


// 执行外部存储器SDRAM的初始化序列
/**
  * @brief  Perform the SDRAM external memory initialization sequence
  * @param  hsdram: SDRAM handle
  * @param  Command: Pointer to SDRAM command structure
  * @retval None
  */
void BSP_SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram  )
{
  FMC_SDRAM_CommandTypeDef Command;
  __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(hsdram, &Command, 0x1000);

  /* Step 2: Insert 100 us minimum delay */
  /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
  HAL_Delay(100);

  /* 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(hsdram, &Command, 0x1000);

  HAL_Delay(100);
  /* Step 4 : Configure a Auto-Refresh command */
  Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
  Command.AutoRefreshNumber = 8;
  Command.ModeRegisterDefinition = 0;

  /* Send the command */
  HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);

  HAL_Delay(100);
  /* 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_2           |
                     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(hsdram, &Command, 0x1000);

  HAL_Delay(100);

  /* Step 6: Set the refresh rate counter */
  /* (15.62 us x Freq) - 20 */
  /* Set the device refresh counter */
  hsdram->Instance->SDRTR |= ((uint32_t)((1292)<< 1));      // 1292 这个1292是官网的,我目前也不知道这个数据是怎么来的 ?? 望指教啊 !!!

HAL_Delay(100);
}
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115653
QQ
发表于 2016-10-25 10:28:38 | 显示全部楼层

回 hpdell 的帖子

hpdell:是的啊,目前测试 32位模式没有问题,就是16位、8位不行,但是 16/8位单独读写貌似又可以

配置如下:

....... (2016-10-24 14:06) 
原理图还是你上次发的那个不。
回复

使用道具 举报

680

主题

3479

回帖

5544

积分

论坛元老

积分
5544
 楼主| 发表于 2016-10-25 14:07:32 | 显示全部楼层

回 eric2013 的帖子

eric2013:原理图还是你上次发的那个不。 (2016-10-25 10:28) 
原理图是上次发的那个

不过最近发现 32位的读写,有时也不行,有时又是正常的,现在有些搞不懂了啊,犯迷糊,
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115653
QQ
发表于 2016-10-26 10:30:56 | 显示全部楼层

回 hpdell 的帖子

hpdell:原理图是上次发的那个

不过最近发现 32位的读写,有时也不行,有时又是正常的,现在有些搞不懂了啊,犯迷糊, (2016-10-25 14:07) 
刷新率的设置看我的这个帖子就行,或者看官方的手册也可以的,都有讲解
http://www.armbbs.cn/forum.php?mod=viewthread&tid=1942
-------------------
回复

使用道具 举报

680

主题

3479

回帖

5544

积分

论坛元老

积分
5544
 楼主| 发表于 2016-10-28 07:24:35 | 显示全部楼层

回 eric2013 的帖子

eric2013:刷新率的设置看我的这个帖子就行,或者看官方的手册也可以的,都有讲解
http://www.armbbs.cn/forum.php?mod=viewthread&tid=1942
-------------------

....... (2016-10-26 10:30)
你好,终于搞定了啊,两片需要一模一样的芯片才行,

另外,这个需要设置为1,   hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;               // 定义在CAS个延时后在等待多少个HCLK时钟才读取数据


现在 读写8bit , 16bit, 32bit 都是非常的稳定了
回复

使用道具 举报

116

主题

800

回帖

1148

积分

至尊会员

积分
1148
QQ
发表于 2016-10-28 15:03:16 | 显示全部楼层
双通道内存
回复

使用道具 举报

680

主题

3479

回帖

5544

积分

论坛元老

积分
5544
 楼主| 发表于 2016-10-28 16:44:16 | 显示全部楼层

回 jcx0324 的帖子

jcx0324:双通道内存 (2016-10-28 15:03) 
是的,吧两片16位的组成一个32位的来使用,目前效果还可以
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-5-9 22:22 , Processed in 0.261286 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表