【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的初始化配置代码及数据比较代码:
uint32_t APS256_WriteReg(XSPI_HandleTypeDef *Ctx, uint32_t Address, uint8_t *Value)
{
XSPI_RegularCmdTypeDef sCommand1={0};
/* Initialize the write register command */
sCommand1.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG;
sCommand1.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES;
sCommand1.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
sCommand1.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
sCommand1.Instruction = WRITE_REG_CMD;
sCommand1.AddressMode = HAL_XSPI_ADDRESS_8_LINES;
sCommand1.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
sCommand1.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE;
sCommand1.Address = Address;
sCommand1.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
sCommand1.DataMode = HAL_XSPI_DATA_8_LINES;
sCommand1.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE;
sCommand1.DataLength = 2;
sCommand1.DummyCycles = 0;
sCommand1.DQSMode = HAL_XSPI_DQS_DISABLE;
/* Configure the command */
if (HAL_XSPI_Command(Ctx, &sCommand1, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
/* Transmission of the data */
if (HAL_XSPI_Transmit(Ctx, (uint8_t *)(Value), HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] Read mode register value
* @param Ctx Component object pointer
* @param Address Register address
* @param Value Register value pointer
* @param LatencyCode Latency used for the access
* @retval error status
*/
uint32_t APS256_ReadReg(XSPI_HandleTypeDef *Ctx, uint32_t Address, uint8_t *Value, uint32_t LatencyCode)
{
XSPI_RegularCmdTypeDef sCommand={0};
/* Initialize the read register command */
sCommand.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG;
sCommand.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES;
sCommand.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
sCommand.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
sCommand.Instruction = READ_REG_CMD;
sCommand.AddressMode = HAL_XSPI_ADDRESS_8_LINES;
sCommand.AddressWidth = HAL_XSPI_ADDRESS_32_BITS;
sCommand.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE;
sCommand.Address = Address;
sCommand.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
sCommand.DataMode = HAL_XSPI_DATA_8_LINES;
sCommand.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE;
sCommand.DataLength = 2;
sCommand.DummyCycles = (LatencyCode - 1U);
sCommand.DQSMode = HAL_XSPI_DQS_ENABLE;
/* Configure the command */
if (HAL_XSPI_Command(Ctx, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
/* Reception of the data */
if (HAL_XSPI_Receive(Ctx, (uint8_t *)Value, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
/**
* @brief Switch from Octal Mode to Hexa Mode on the memory
* @param None
* @retval None
*/
static void Configure_APMemory(void)
{
/* MR0 register for read and write */
uint8_t regW_MR0[2]={0x24,0x8D}; /* To configure AP memory Latency Type and drive Strength */
uint8_t regR_MR0[2]={0};
/* MR8 register for read and write */
uint8_t regW_MR8[2]={0x4B,0x08}; /* To configure AP memory Burst Type */
uint8_t regR_MR8[2]={0};
/*Read Latency */
uint8_t latency=6;
/* Configure Read Latency and drive Strength */
if (APS256_WriteReg(&hxspi1, MR0, regW_MR0) != HAL_OK)
{
Error_Handler();
}
/* Check MR0 configuration */
if (APS256_ReadReg(&hxspi1, MR0, regR_MR0, latency ) != HAL_OK)
{
Error_Handler();
}
/* Check MR0 configuration */
if (regR_MR0 [0] != regW_MR0 [0])
{
Error_Handler() ;
}
/* Configure Burst Length */
if (APS256_WriteReg(&hxspi1, MR8, regW_MR8) != HAL_OK)
{
Error_Handler();
}
/* Check MR8 configuration */
if (APS256_ReadReg(&hxspi1, MR8, regR_MR8, 6) != HAL_OK)
{
Error_Handler();
}
if (regR_MR8[0] != regW_MR8[0])
{
Error_Handler() ;
}
}
static void MX_XSPI1_Init(void)
{
/* USER CODE BEGIN XSPI1_Init 0 */
/* USER CODE END XSPI1_Init 0 */
XSPIM_CfgTypeDef sXspiManagerCfg = {0};
/* USER CODE BEGIN XSPI1_Init 1 */
/* USER CODE END XSPI1_Init 1 */
/* XSPI1 parameter configuration*/
hxspi1.Instance = XSPI1;
hxspi1.Init.FifoThresholdByte = 4;
hxspi1.Init.MemoryMode = HAL_XSPI_SINGLE_MEM;
hxspi1.Init.MemoryType = HAL_XSPI_MEMTYPE_APMEM_16BITS;
hxspi1.Init.MemorySize = HAL_XSPI_SIZE_64MB;
hxspi1.Init.ChipSelectHighTimeCycle = 1;
hxspi1.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE;
hxspi1.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0;
hxspi1.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED;
hxspi1.Init.ClockPrescaler = 0;
hxspi1.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE;
hxspi1.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_DISABLE;
hxspi1.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_NONE;
hxspi1.Init.MaxTran = 0;
hxspi1.Init.Refresh = 0;
hxspi1.Init.MemorySelect = HAL_XSPI_CSSEL_NCS1;
if (HAL_XSPI_Init(&hxspi1) != HAL_OK)
{
Error_Handler();
}
sXspiManagerCfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS1;
sXspiManagerCfg.IOPort = HAL_XSPIM_IOPORT_1;
if (HAL_XSPIM_Config(&hxspi1, &sXspiManagerCfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN XSPI1_Init 2 */
/* USER CODE END XSPI1_Init 2 */
}
看看比对结果!一次成功!
其实,像这种评估板,如果比较失败,则可以肯定是咱们自己的xspi的配置参数出现了错误。开发板本身不会出现问题!这也是原型验证的必要之处吧!——软件、硬件,两者总得有一个是靠谱的吧!
|