前言

之前我开发的设备使用主控芯片是STM32F429,查询资料STM32H723系列和F429是完全pin-to-pin。故使用原主控板焊接H723测试下效果。

在我看来STM32H723和之前F429系列最大的不同有以下方面:

  • 主频和内部RAM增强扩容;
  • 引入了MPU和cache;
  • 电源域复杂,H7引入了(D1/D2/D3),更有利于低功耗处理;
  • 整体上接近SOC芯片了

目前网上看到的关于STM32H723的资料较少,自己在调试过程中遇到了HardFault问题.当代码语句运行到MX_FMC_Init()时触发。先将解决问题的过程记录如下,供其它开发的童鞋参考。

1. 时钟配置

2. FMC-GPIO配置

注意:在STM32H7、STM32F429系列的芯片其外设是FMC,而STM32F1\F407系列的芯片其外设是FSMC,两者的区别请参考以下文章:

【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(一)_fmc 自动刷新sdram-CSDN博客

3. FMC-SDRAM配置

特别说明:主控工作在480MHz时,FMC的工作频率是240MHz.

选择SDRAM1,SDRAM芯片W9825G6KH的最大工作频率是200MHz。

FMC驱动SDRAM使用了二分频,工作在120MHz,那么一个时钟周期是1/120M=8.33ns

这部分参考了以下的文章:

【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(一)_fmc 自动刷新sdram-CSDN博客

4. MPU配置 CORTEX-M7

Cortex-m7的默认配置是无法使用SDRAM的,因为SDRAM的地址有默认的MPU保护限制。

必须关闭这部分的mpu设置,否则会直接HardFault.

这部分参考了以下的文章:

STM32H743+CubeMX-梳理MPU的设置_background region privileged accesses only-CSDN博客

STM32H7XX的MPU和Cache总结_stm32h7 mpu-CSDN博客

5. 具体代码

#define SDRAM_Size (32*1024*1024)                               // 32M字节
#define SDRAM_BANK_ADDR     ((uint32_t)0xC0000000) 				// FMC SDRAM 数据基地址
#define FMC_COMMAND_TARGET_BANK   FMC_SDRAM_CMD_TARGET_BANK1	// SDRAM 的bank选择
#define SDRAM_TIMEOUT     ((uint32_t)0x1000) 					// 超时判断时间
 
#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) 
FMC_SDRAM_CommandTypeDef command;// 控制指令
 
/******************************************************************************************************
*	函 数 名: SDRAM_Initialization_Sequence
*	入口参数: hsdram - SDRAM_HandleTypeDef定义的变量,即表示定义的sdram
*				 Command	- 控制指令
*	返 回 值: 无
*	函数功能: SDRAM 参数配置
*	说    明: 配置SDRAM相关时序和控制方式
*******************************************************************************************************/
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
{
	__IO uint32_t tmpmrd = 0;
 
	/* Configure a clock configuration enable command 时钟配置使能*/
	Command->CommandMode 				= FMC_SDRAM_CMD_CLK_ENABLE;	// 开启SDRAM时钟 
	Command->CommandTarget 				= FMC_COMMAND_TARGET_BANK; 	// 选择要控制的区域
	Command->AutoRefreshNumber 	    	= 1;
	Command->ModeRegisterDefinition 	= 0;
 
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);	// 发送控制指令
	HAL_Delay(1);		// 延时等待,至少200us
 
	/* Configure a PALL (precharge all) command 对所有存储区域预充电*/ 
	Command->CommandMode 				= FMC_SDRAM_CMD_PALL;		// 预充电命令
	Command->CommandTarget 				= FMC_COMMAND_TARGET_BANK;	// 选择要控制的区域
	Command->AutoRefreshNumber 		    = 1;
	Command->ModeRegisterDefinition 	= 0;
 
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);  // 发送控制指令
 
	/* Configure a Auto-Refresh command 设置自动刷新次数*/ 
	Command->CommandMode 				= FMC_SDRAM_CMD_AUTOREFRESH_MODE;	// 使用自动刷新
	Command->CommandTarget 				= FMC_COMMAND_TARGET_BANK;          // 选择要控制的区域
	Command->AutoRefreshNumber			= 8;                                // 自动刷新次数,发送 至少 2 个(通常是 8 个)Auto-Refresh 命令
	Command->ModeRegisterDefinition 	= 0;
 
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);	// 发送控制指令
 
	/* Program the external memory mode register */
    //配置模式寄存器,SDRAM的bit0-bit2为指定突发访问的长度
    //bit3为指定突发访问的类型,bit4-bit6为CAS值,bit7和bit8为运行模式
    //bit9为指定的写突发模式,bit10和bit11位保留位
	tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2               |//设置突发长度:2(可以是1/2/4/8)
							SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |//设置突发类型:连续(可以是连续/交错)
							SDRAM_MODEREG_CAS_LATENCY_3           |//设置CAS值:3(可以是2/3)
							SDRAM_MODEREG_OPERATING_MODE_STANDARD |//设置操作模式:0,标准模式
							SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;  //设置突发写模式:1,单点访问
 
	Command->CommandMode            = FMC_SDRAM_CMD_LOAD_MODE;	// 加载模式寄存器命令
	Command->CommandTarget          = FMC_COMMAND_TARGET_BANK;	// 选择要控制的区域
	Command->AutoRefreshNumber 		= 1;
	Command->ModeRegisterDefinition = tmpmrd;
 
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);	// 发送控制指令
    
	//刷新频率计数器(以SDCLK频率计数),计算方法:
	//COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
    //我们使用的SDRAM刷新周期为64ms,行数为8192(2^13).SDCLK=240/2=120Mhz,8.33ns;
	//所以,COUNT=(64*1000/8192)us*120-20=918(20为刷新等待冗余)
	// Refresh_Count = (SDRAM_Refresh_Period_us × FMC_Clock_MHz) / Number_of_Rows - 20
	HAL_SDRAM_ProgramRefreshRate(hsdram, 918);  // 配置刷新率
}

6. 测试效果

void fsmc_sdram_test(void)
{  
	__IO uint32_t i=0;  	  
	__IO uint32_t temp=0;	   
	__IO uint32_t sval=0;  				   
	
	for(i=0;i<32*1024*1024;i+=16*1024)
	{
		*(__IO uint32_t *)(SDRAM_BANK_ADDR+i)=temp; 
		temp++;
	}
			  
 	for(i=0;i<32*1024*1024;i+=16*1024) 
	{	
  		temp=*(__IO uint32_t *)(SDRAM_BANK_ADDR+i);
		if(i==0)
			sval=temp;
 		else if(temp<=sval)
			break;	   		   
		printf("SDRAM Capacity:%dKB\r\n",(uint16_t )(temp-sval+1)*16);
 	}					 
}

7. 其它参考资料

参考手册:《rm0468-stm32h723733-stm32h725735-and-stm32h730-value-line-advanced-armbased-32bit-mcus-stmicroelectronics》

用户手册:《STM32H723ZGT6_规格书_ST(意法半导体)单片机(MCUMPUSOC)规格书》

《安富莱_STM32-V7开发板_用户手册,含BSP驱动包设计(V3.5)》

《C62246_同步动态随机存取内存(SDRAM)_W9825G6KH-6_规格书_WJ279889》

25. FMC—扩展外部SDRAM — [野火]STM32 HAL库开发实战指南——基于野火F7与H7系列开发板 文档

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐