4. 外部RAM
动机
在该步骤中,我们将使能外部SDRAM。 图形应用通常需要外部RAM,在许多分辨率下所需帧缓存较大,而无法使用内部RAM。 某些应用可能使用两到三个帧缓存,因此更加需要外部RAM。
Note
当帧缓存要放在外部RAM时,确保外部RAM
- 可读可写。
- 并以所需速度(通常为最大速度)运行。
目标
本节旨在启用外部RAM,并从中读取和写入数据。
验证
以下是本节的验证点:
验证点 | 基本原理 |
---|---|
外部RAM可读 | 外部RAM可用于帧缓冲区位置 |
外部RAM可写 | 外部RAM可用于帧缓冲区位置 |
外部RAM性能 | 使用外部RAM作为帧缓存时,图形处理性能可接受 |
先决条件
以下是此步骤的先决条件:
- 有关RAM的信息,通常为数据手册
- 有关MCU与外部RAM之间的连接的信息
执行
在STM32CubeMX中,通过“Connectivity”->“FMC”->“SDRAM1”来配置外部SDRAM控制器:
AHB时钟(HCLK) 是FMC存储控制器的参考时钟。 检查“时钟配置”下的时钟频率,并使用该频率计算各种SDRAM时钟周期。
请记住配置用于SDRAM的所有GPIO:
进一步配置
对于某些RAM芯片,还必须进行其他特定的配置。 这部分不能在STM32CubeMX中配置,而必须在C代码中完成。 STM32Cube HAL包含用户向设备发送命令的函数。 下面为一个示例:
main.c
FMC_SDRAM_CommandTypeDef Command;
/* 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);
测试 RAM
配置外部RAM后,务必对其进行测试。 我们应至少测试以下内容:
- RAM在调试器中可见
- RAM在整个范围内可读可写
- 性能符合预期
存储控制器根据外部存储器的类型使用其固定地址映射。 检查微控制器的数据手册以确认其地址。 SDRAM通常映射到0xC0000000(存储区域1) 或0xD0000000(存储区域2) 。
测试RAM在调试器中可见。
使能RAM后的第一个测试为借助调试器访问它。 这样就可以轻松确认是否可以读写存储器。 只需使用存储器浏览器打开以下地址:
RAM在整个范围内可读可写
下一个测试为编写小程序,将更多数据写入外部存储器。 最好测试整个存储器。 以下是起点:
uint32_t *externalRAM = 0xC000000;
const uint32_t size = 1000;
//write external RAM
for(int i = 0; i < size; i++)
{
externalRAM[i] = i;
}
现在,在调试器中再次检查存储器。 这可以显示某些类型的错误,例如,某些地址引脚是否未连接或未交换。 您还应尝试不同大小的写入值。 仅仅写入小数字(如0、1、2、3) 往往无法揭示某些数据引脚是否正常连接或损坏。
我们可以通过简单程序来读取存储器:
uint32_t *externalRAM = 0xC000000;
const uint32_t size = 1000;
//read external RAM
for(int i = 0; i < size; i++)
{
ASSERT(externalRAM[i] == i, "external RAM not as expected");
}
请记住,此类测试无法确定地址是否错误。
欲测试所有存储单元。 要么通过运行更长的循环,要么随意更改起始地址。
性能符合预期
我们现在需要测试外部RAM的性能。 当帧缓存位于外部存储器中时,性能很重要。 缓慢的存储器会使系统的图形处理性能降低。
测试读取、写入和修改RAM的速度。 通常,图形应用会将许多数据从一个存储器复制到另一个存储器。 在绘图操作期间将大量写入帧缓冲,而在传输至显示屏时将进行大量读取操作。 我们可通过测试程序来模拟这些操作:
volatile uint32_t *externalRAM = 0xC000000;
uint32_t sourcedata[10000];
const uint32_t size = 10000;
int begin = HAL_GetTick();
//write external RAM
for(int i = 0; i < size; i++)
{
externalRAM[i] = sourcedata[i];
}
int end = HAL_GetTick();
int begin = HAL_GetTick();
//Read external RAM
for(int i = 0; i < size; i++)
{
sourcedata[i] = externalRAM[i];
}
int end = HAL_GetTick();
当在背景上混合图形时,图形处理软件可在帧缓冲中读取和写入数据。
//Time modifying external RAM
int begin = HAL_GetTick();
for(int i = 0; i < size; i++)
{
externalRAM[i] += 2;
}
int end = HAL_GetTick();
根据您的存储器速度和想要的精度,您可能希望循环测试100次,以使结果更可靠。
如果外部RAM时钟过快,则可能在读取或写入操作期间导致错误。 通过这些较简单的测试可能很难看到这一点,但这在显示屏上可以直观地感受到。