[STM32H7] 【STM32H7S78-DK测评】扩展内存,PSRAM映射实验

[复制链接]
5052|7
 楼主| jobszheng 发表于 2024-10-14 01:42 | 显示全部楼层 |阅读模式
【STM32H7S78-DK测评】扩展内存,PSRAM映射实验

在嵌入式项目里面,集成到MCU中的SRAM一般很小。在大多数应用项目里片上的SRAM都可以满足项目需求的,不过,当像本次DIY的STM32H7S78-DK评估板中有一个高分辨率的大展时,片上的620KB的SRAM就有点微不足道了。当然,ST官方也贴心地提供了完美解决方案:板载了一块容量高达256-Mbit的PSRAM。不过,强大的STM32H7S78使用了Hex-SPI的外设接口,超级快的外设接口,它的性能如何?是否实用呢?今天我就带大家来验证一下!

前面两个帖子有讲过,STM32H7S78采用了BootFllash的程序架构,我们一般仅编写App程序即可,但本次实验的内容是在Boot程序中配置并实现的,因此,我们的工程也仅有Boot程序。接下来,我们构建验证PSRAM的例程。

  • 我们先初始化Hex-SPI外设及PSRAM的配置参数,完成内存映射;
  • 生成一个数组,预先初始化好我们的数据;
  • 将数组的内容写入到指定地址(映射的地址0x90000000);
  • 将指定地址的数据内容回读;
  • 与写入数据两者比较,如果一致,则打印“校对成功”的调试字符;

分享一下PSRAM的初始化配置代码及数据比较代码:

  1. uint32_t APS256_WriteReg(XSPI_HandleTypeDef *Ctx, uint32_t Address, uint8_t *Value)
  2. {
  3.   XSPI_RegularCmdTypeDef sCommand1={0};
  4.   
  5.   /* Initialize the write register command */
  6.   sCommand1.OperationType      = HAL_XSPI_OPTYPE_COMMON_CFG;
  7.   sCommand1.InstructionMode    = HAL_XSPI_INSTRUCTION_8_LINES;
  8.   sCommand1.InstructionWidth    = HAL_XSPI_INSTRUCTION_8_BITS;
  9.   sCommand1.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
  10.   sCommand1.Instruction        = WRITE_REG_CMD;
  11.   sCommand1.AddressMode        = HAL_XSPI_ADDRESS_8_LINES;
  12.   sCommand1.AddressWidth        = HAL_XSPI_ADDRESS_32_BITS;
  13.   sCommand1.AddressDTRMode     = HAL_XSPI_ADDRESS_DTR_ENABLE;
  14.   sCommand1.Address            = Address;
  15.   sCommand1.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
  16.   sCommand1.DataMode           = HAL_XSPI_DATA_8_LINES;
  17.   sCommand1.DataDTRMode        = HAL_XSPI_DATA_DTR_ENABLE;
  18.   sCommand1.DataLength         = 2;
  19.   sCommand1.DummyCycles        = 0;
  20.   sCommand1.DQSMode            = HAL_XSPI_DQS_DISABLE;
  21.   
  22.   /* Configure the command */
  23.   if (HAL_XSPI_Command(Ctx, &sCommand1, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  24.   {
  25.     return HAL_ERROR;
  26.   }
  27.   
  28.   /* Transmission of the data */
  29.   if (HAL_XSPI_Transmit(Ctx, (uint8_t *)(Value), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  30.   {
  31.     return HAL_ERROR;
  32.   }
  33.   
  34.   return HAL_OK;
  35. }

  36. /**
  37. * [url=home.php?mod=space&uid=247401]@brief[/url]  Read mode register value
  38. * @param  Ctx Component object pointer
  39. * @param  Address Register address
  40. * @param  Value Register value pointer
  41. * @param  LatencyCode Latency used for the access
  42. * @retval error status
  43. */
  44. uint32_t APS256_ReadReg(XSPI_HandleTypeDef *Ctx, uint32_t Address, uint8_t *Value, uint32_t LatencyCode)
  45. {
  46.   XSPI_RegularCmdTypeDef sCommand={0};
  47.   
  48.   /* Initialize the read register command */
  49.   sCommand.OperationType      = HAL_XSPI_OPTYPE_COMMON_CFG;
  50.   sCommand.InstructionMode    = HAL_XSPI_INSTRUCTION_8_LINES;
  51.   sCommand.InstructionWidth    = HAL_XSPI_INSTRUCTION_8_BITS;
  52.   sCommand.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
  53.   sCommand.Instruction        = READ_REG_CMD;
  54.   sCommand.AddressMode        = HAL_XSPI_ADDRESS_8_LINES;
  55.   sCommand.AddressWidth        = HAL_XSPI_ADDRESS_32_BITS;
  56.   sCommand.AddressDTRMode     = HAL_XSPI_ADDRESS_DTR_ENABLE;
  57.   sCommand.Address            = Address;
  58.   sCommand.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
  59.   sCommand.DataMode           = HAL_XSPI_DATA_8_LINES;
  60.   sCommand.DataDTRMode        = HAL_XSPI_DATA_DTR_ENABLE;
  61.   sCommand.DataLength            = 2;
  62.   sCommand.DummyCycles        = (LatencyCode - 1U);
  63.   sCommand.DQSMode            = HAL_XSPI_DQS_ENABLE;
  64.   
  65.   /* Configure the command */
  66.   if (HAL_XSPI_Command(Ctx, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  67.   {
  68.     return HAL_ERROR;
  69.   }
  70.   
  71.   /* Reception of the data */
  72.   if (HAL_XSPI_Receive(Ctx, (uint8_t *)Value, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  73.   {
  74.     return HAL_ERROR;
  75.   }
  76.   
  77.   return HAL_OK;
  78. }

  79. /**
  80. * @brief  Switch from Octal Mode to Hexa Mode on the memory
  81. * @param  None
  82. * @retval None
  83. */
  84. static void Configure_APMemory(void)
  85. {
  86.   /* MR0 register for read and write */
  87.   uint8_t regW_MR0[2]={0x24,0x8D}; /* To configure AP memory Latency Type and drive Strength */
  88.   uint8_t regR_MR0[2]={0};
  89.   
  90.   /* MR8 register for read and write */
  91.   uint8_t regW_MR8[2]={0x4B,0x08}; /* To configure AP memory Burst Type */
  92.   uint8_t regR_MR8[2]={0};
  93.   
  94.   /*Read Latency */
  95.   uint8_t latency=6;
  96.   
  97.   /* Configure Read Latency and drive Strength */
  98.   if (APS256_WriteReg(&hxspi1, MR0, regW_MR0) != HAL_OK)
  99.   {
  100.     Error_Handler();
  101.   }
  102.   
  103.   /* Check MR0 configuration */
  104.   if (APS256_ReadReg(&hxspi1, MR0, regR_MR0, latency ) != HAL_OK)
  105.   {
  106.     Error_Handler();
  107.   }
  108.   
  109.   /* Check MR0 configuration */
  110.   if (regR_MR0 [0] != regW_MR0 [0])
  111.   {
  112.     Error_Handler() ;
  113.   }
  114.   
  115.   /* Configure Burst Length */
  116.   if (APS256_WriteReg(&hxspi1, MR8, regW_MR8) != HAL_OK)
  117.   {
  118.     Error_Handler();
  119.   }
  120.   
  121.   /* Check MR8 configuration */
  122.   if (APS256_ReadReg(&hxspi1, MR8, regR_MR8, 6) != HAL_OK)
  123.   {
  124.     Error_Handler();
  125.   }
  126.   
  127.   if (regR_MR8[0] != regW_MR8[0])
  128.   {
  129.     Error_Handler() ;
  130.   }
  131. }

  132. static void MX_XSPI1_Init(void)
  133. {

  134.   /* USER CODE BEGIN XSPI1_Init 0 */

  135.   /* USER CODE END XSPI1_Init 0 */

  136.   XSPIM_CfgTypeDef sXspiManagerCfg = {0};

  137.   /* USER CODE BEGIN XSPI1_Init 1 */

  138.   /* USER CODE END XSPI1_Init 1 */
  139.   /* XSPI1 parameter configuration*/
  140.   hxspi1.Instance = XSPI1;
  141.   hxspi1.Init.FifoThresholdByte = 4;
  142.   hxspi1.Init.MemoryMode = HAL_XSPI_SINGLE_MEM;
  143.   hxspi1.Init.MemoryType = HAL_XSPI_MEMTYPE_APMEM_16BITS;
  144.   hxspi1.Init.MemorySize = HAL_XSPI_SIZE_64MB;
  145.   hxspi1.Init.ChipSelectHighTimeCycle = 1;
  146.   hxspi1.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE;
  147.   hxspi1.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0;
  148.   hxspi1.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED;
  149.   hxspi1.Init.ClockPrescaler = 0;
  150.   hxspi1.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE;
  151.   hxspi1.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_DISABLE;
  152.   hxspi1.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_NONE;
  153.   hxspi1.Init.MaxTran = 0;
  154.   hxspi1.Init.Refresh = 0;
  155.   hxspi1.Init.MemorySelect = HAL_XSPI_CSSEL_NCS1;
  156.   if (HAL_XSPI_Init(&hxspi1) != HAL_OK)
  157.   {
  158.     Error_Handler();
  159.   }
  160.   sXspiManagerCfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS1;
  161.   sXspiManagerCfg.IOPort = HAL_XSPIM_IOPORT_1;
  162.   if (HAL_XSPIM_Config(&hxspi1, &sXspiManagerCfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  163.   {
  164.     Error_Handler();
  165.   }
  166.   /* USER CODE BEGIN XSPI1_Init 2 */

  167.   /* USER CODE END XSPI1_Init 2 */

  168. }

看看比对结果!一次成功!

psram.png


其实,像这种评估板,如果比较失败,则可以肯定是咱们自己的xspi的配置参数出现了错误。开发板本身不会出现问题!这也是原型验证的必要之处吧!——软件、硬件,两者总得有一个是靠谱的吧!




k2715009743 发表于 2024-10-16 09:10 | 显示全部楼层
sukermyz 发表于 2024-10-23 22:12 | 显示全部楼层
非常赞的资料。
Amazingxixixi 发表于 2024-10-31 16:20 | 显示全部楼层
学习一下如何修改
 楼主| jobszheng 发表于 2024-10-31 16:44 | 显示全部楼层

这个过程倒是没有啥。
就是读datasheet的过程太煎熬了
suncat0504 发表于 2024-10-31 17:29 | 显示全部楼层
能扩展内存,性能确实强。有了扩展内存,方便做图像类的处理了。谢谢分享,学习了。
地瓜patch 发表于 2024-10-31 18:54 来自手机 | 显示全部楼层
这个映射不是必须的,什么情况下要考虑映射
 楼主| jobszheng 发表于 2024-11-1 16:48 | 显示全部楼层
地瓜patch 发表于 2024-10-31 18:54
这个映射不是必须的,什么情况下要考虑映射

这款MCU的片上资源非常有限。
所以基本上一定要使用外扩的资源,如外扩的RAM与Flash
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:嵌入式技术专家
简介:热爱开源,乐于分享。在嵌入式技术领域里面,主攻通讯协议,Modbus,TCP/IP以及虚拟化和RTOS

31

主题

746

帖子

23

粉丝
快速回复 在线客服 返回列表 返回顶部