正点原子STM32H743配置 SDRAM
开发板 正点原子STM32H743 阿波罗
固件包 STM32Cube MCU Package for STM32H7 1.12.1
开发工具 STM32CubeMX + STM32CubeIDE
STM32H743IITX_FLASH.ld/* 修改 */
MEMORY
{FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048KDTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128KRAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512KRAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288KRAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64KITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64KSDRAM_D1 (xrw) : ORIGIN = 0xC0000000, LENGTH = 32M
}/* 增加 */.sdram_data (NOLOAD) :{. = ALIGN(4);__sdram_data_start__ = .;*(.sdram_data)*(.sdram_data*). = ALIGN(4);__sdram_data_end__ = .;} >SDRAM_D1
bsp_sdarm.h#ifndef BSP_SDRAM_H_
#define BSP_SDRAM_H_#ifdef __cplusplus
extern "C" {
#endif#include "main.h"void bsp_SDRAMInit(void);
uint32_t bsp_TestExtSDRAM(void);
void bsp_SDRAMInitColor(void);#ifdef __cplusplus
}
#endif#endif /* BSP_SDRAM_H_ */
bsp_sdarm.c#include "bsp_sdram.h"#include "fmc.h"#include <stdio.h>/* SDRAM配置参数 */
#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)#define EXT_SDRAM_ADDR ((uint32_t)0xC0000000)
#define EXT_SDRAM_SIZE (32 * 1024 * 1024)uint8_t bsp_SDRAMSendCmd(uint8_t bankx, uint8_t cmd, uint8_t refresh,uint16_t regval) {uint32_t target_bank = 0;FMC_SDRAM_CommandTypeDef command;if (bankx == 0) {target_bank = FMC_SDRAM_CMD_TARGET_BANK1;} else if (bankx == 1) {target_bank = FMC_SDRAM_CMD_TARGET_BANK2;}command.CommandMode = cmd; /* 命令 */command.CommandTarget = target_bank; /* 目标SDRAM存储区域 */command.AutoRefreshNumber = refresh; /* 自刷新次数 */command.ModeRegisterDefinition = regval; /* 要写入模式寄存器的值 */if (HAL_SDRAM_SendCommand(&hsdram1, &command, 0X1000) == HAL_OK) /* 向SDRAM发送命令 */{return 0;} else {return 1;}
}void bsp_SDRAMInit(void) {uint32_t temp = 0;/* SDRAM控制器初始化完成以后还需要按照如下顺序初始化SDRAM */bsp_SDRAMSendCmd(0, FMC_SDRAM_CMD_CLK_ENABLE, 1, 0); /* 时钟配置使能 */HAL_Delay(1); /* 至少延时500us */bsp_SDRAMSendCmd(0, FMC_SDRAM_CMD_PALL, 1, 0); /* 对所有存储区预充电 */bsp_SDRAMSendCmd(0, FMC_SDRAM_CMD_AUTOREFRESH_MODE, 8, 0); /* 设置自刷新次数 *//* 配置模式寄存器,SDRAM的bit0~bit2为指定突发访问的长度,* bit3为指定突发访问的类型,bit4~bit6为CAS值,bit7和bit8为运行模式* bit9为指定的写突发模式,bit10和bit11位保留位 */temp = (uint32_t) SDRAM_MODEREG_BURST_LENGTH_1 | /* 设置突发长度:1(可以是1/2/4/8) */SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | /* 设置突发类型:连续(可以是连续/交错) */SDRAM_MODEREG_CAS_LATENCY_2 | /* 设置CAS值:2(可以是2/3) */SDRAM_MODEREG_OPERATING_MODE_STANDARD | /* 设置操作模式:0,标准模式 */SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; /* 设置突发写模式:1,单点访问 */bsp_SDRAMSendCmd(0, FMC_SDRAM_CMD_LOAD_MODE, 1, temp); /* 设置SDRAM的模式寄存器 *//*** 刷新频率计数器(以SDCLK频率计数),计算方法:* COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数* 我们使用的SDRAM刷新周期为64ms,SDCLK=220/2=110Mhz,行数为8192(2^13).* 所以,COUNT=64*1000*110/8192-20=839* COUNT=64*1000*100/8192-20=761*/if (HAL_OK != HAL_SDRAM_ProgramRefreshRate(&hsdram1, 761)) /* 设置刷新频率 */{printf("SDRAM W9825G6KH Init failed! \r\n");}
}/*********************************************************************************************************** 函 数 名: bsp_TestExtSDRAM* 功能说明: 扫描测试外部SDRAM的全部单元。* 形 参: 无* 返 回 值: 0 表示测试通过; 大于0表示错误单元的个数。**********************************************************************************************************/
uint32_t bsp_TestExtSDRAM(void) {uint32_t i;uint32_t *pSRAM;uint8_t *pBytes;uint32_t err;const uint8_t ByteBuf[4] = { 0x55, 0xA5, 0x5A, 0xAA };/* 写SDRAM */pSRAM = (uint32_t*) EXT_SDRAM_ADDR;for (i = 0; i < EXT_SDRAM_SIZE / 4; i++) {*pSRAM++ = i;}/* 读SDRAM */err = 0;pSRAM = (uint32_t*) EXT_SDRAM_ADDR;for (i = 0; i < EXT_SDRAM_SIZE / 4; i++) {if (*pSRAM++ != i) {err++;}}if (err > 0) {return (4 * err);}/* 对SDRAM 的数据求反并写入 */pSRAM = (uint32_t*) EXT_SDRAM_ADDR;for (i = 0; i < EXT_SDRAM_SIZE / 4; i++) {*pSRAM = ~*pSRAM;pSRAM++;}/* 再次比较SDRAM的数据 */err = 0;pSRAM = (uint32_t*) EXT_SDRAM_ADDR;for (i = 0; i < EXT_SDRAM_SIZE / 4; i++) {if (*pSRAM++ != (~i)) {err++;}}if (err > 0) {return (4 * err);}/* 测试按字节方式访问, 目的是验证 FSMC_NBL0 、 FSMC_NBL1 口线 */pBytes = (uint8_t*) EXT_SDRAM_ADDR;for (i = 0; i < sizeof(ByteBuf); i++) {*pBytes++ = ByteBuf[i];}/* 比较SDRAM的数据 */err = 0;pBytes = (uint8_t*) EXT_SDRAM_ADDR;for (i = 0; i < sizeof(ByteBuf); i++) {if (*pBytes++ != ByteBuf[i]) {err++;}}if (err > 0) {return err;}return 0;
}void bsp_SDRAMInitColor(void) {uint32_t *pSRAM;uint32_t i;pSRAM = (uint32_t*) EXT_SDRAM_ADDR;for (i = 0; i < EXT_SDRAM_SIZE / 4; i++) {*pSRAM++ = 0x001f001f;}
}