不含stm32 底层的代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
MyStm32Code/bsp/Src/bsp_sdram.c

171 lines
5.5 KiB

#include "fmc.h"
#include "bsp_sdram.h"
extern SDRAM_HandleTypeDef hsdram1;
static FMC_SDRAM_CommandTypeDef Command;
static SDRAM_HandleTypeDef *sdramHandle = &hsdram1;
MY_SDRAM_TypeDef my_sdram ={
SDRAM_Init,
SDRAM_Test,
};
static void SDRAM_delay(__IO uint32_t nCount)
{
__IO uint32_t index = 0;
for (index = (100000 * nCount); index != 0; index--)
{
}
}
void SDRAM_Init()
{
// MX_FMC_Init();
SDRAM_Initialization_Sequence(sdramHandle);
}
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{
uint32_t temp = 0;
// SDRAM控制器初始化完成以后还需要按照如下顺序初始化SDRAM
SDRAM_Send_Cmd(2, FMC_SDRAM_CMD_CLK_ENABLE, 1, 0); // 时钟配置使能
HAL_Delay(1);
// delay_us(500); //至少延时200us
SDRAM_Send_Cmd(2, FMC_SDRAM_CMD_PALL, 1, 0); // 对所有存储区预充电
SDRAM_Send_Cmd(2, 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_3 | // 设置CAS值:3(可以是2/3)
SDRAM_MODEREG_OPERATING_MODE_STANDARD | // 设置操作模式:0,标准模式
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; // 设置突发写模式:1,单点访问
SDRAM_Send_Cmd(2, FMC_SDRAM_CMD_LOAD_MODE, 1, temp); // 设置SDRAM的模式寄存器
// 刷新频率计数器(以SDCLK频率计数),计算方法:
// COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
// 我们使用的SDRAM刷新周期为64ms,SDCLK=216/2=108Mhz,行数为8192(2^13).
// 所以,COUNT=64*1000*108/8192-20=823
// 168 MHz COUNT=64*1000*84 /8192-20= 3656
HAL_SDRAM_ProgramRefreshRate(sdramHandle, 823);
}
// 向SDRAM发送命令
// bankx:2,向BANK2上面的SDRAM发送指令 FMC_SDRAM_CMD_TARGET_BANK2 SDCKE1+SDNE1
// 1,向BANK1上面的SDRAM发送指令 FMC_SDRAM_CMD_TARGET_BANK1 SDCKE0+SDNE0
// cmd:指令(0,正常模式/1,时钟配置使能/2,预充电所有存储区/3,自动刷新/4,加载模式寄存器/5,自刷新/6,掉电)
// refresh:自刷新次数
// regval:模式寄存器的定义
// 返回值:0,正常;1,失败.
uint8_t SDRAM_Send_Cmd(uint8_t bankx, uint8_t cmd, uint8_t refresh, uint16_t regval)
{
uint32_t target_bank = 0;
FMC_SDRAM_CommandTypeDef Command;
if (bankx == 1)
target_bank = FMC_SDRAM_CMD_TARGET_BANK1;
else if (bankx == 2)
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(sdramHandle, &Command, 0X1000) == HAL_OK) // 向SDRAM发送命令
{
return 0;
}
else
return 1;
}
// 在指定地址(WriteAddr+Bank5_SDRAM_ADDR)开始,连续写入n个字节.
// pBuffer:字节指针
// WriteAddr:要写入的地址
// n:要写入的字节数
void FMC_SDRAM_WriteBuffer(uint8_t *pBuffer, uint32_t WriteAddr, uint32_t n)
{
for (; n != 0; n--)
{
*(volatile unsigned char *)(Bank4_SDRAM_ADDR + WriteAddr) = *pBuffer;
WriteAddr++;
pBuffer++;
}
}
// 在指定地址((WriteAddr+Bank5_SDRAM_ADDR))开始,连续读出n个字节.
// pBuffer:字节指针
// ReadAddr:要读出的起始地址
// n:要写入的字节数
void FMC_SDRAM_ReadBuffer(uint8_t *pBuffer, uint32_t ReadAddr, uint32_t n)
{
for (; n != 0; n--)
{
*pBuffer++ = *(volatile unsigned char *)(Bank4_SDRAM_ADDR + ReadAddr);
ReadAddr++;
}
}
uint8_t SDRAM_Test(uint32_t count)
{
/*写入数据计数器*/
uint32_t counter = 0;
uint8_t ubWritedata_8b = 0, ubReaddata_8b = 0;
uint16_t uhWritedata_16b = 0, uhReaddata_16b = 0;
/*按8位格式读写数据,并校验*/
for (counter = 0x00; counter < count; counter++)
{
*(__IO uint8_t *)(Bank4_SDRAM_ADDR + counter) = (uint8_t)0x0;
}
/* 向整个SDRAM写入数据 8位 */
for (counter = 0; counter < count; counter++)
{
*(__IO uint8_t *)(Bank4_SDRAM_ADDR + counter) = (uint8_t)(ubWritedata_8b + counter);
}
/* 读取 SDRAM 数据并检测*/
for (counter = 0; counter < count; counter++)
{
ubReaddata_8b = *(__IO uint8_t *)(Bank4_SDRAM_ADDR + counter); // 从该地址读出数据
if (ubReaddata_8b != (uint8_t)(ubWritedata_8b + counter)) // 检测数据,若不相等,跳出函数,返回检测失败结果。
{
// SDRAM_ERROR("8位数据读写错误!");
return 0;
}
}
/*按16位格式读写数据,并检测*/
/* 把SDRAM数据全部重置为0 */
for (counter = 0x00; counter < count / 2; counter++)
{
*(__IO uint16_t *)(Bank4_SDRAM_ADDR + 2 * counter) = (uint16_t)0x00;
}
/* 向整个SDRAM写入数据 16位 */
for (counter = 0; counter < count / 2; counter++)
{
*(__IO uint16_t *)(Bank4_SDRAM_ADDR + 2 * counter) = (uint16_t)(uhWritedata_16b + counter);
}
/* 读取 SDRAM 数据并检测*/
for (counter = 0; counter < count / 2; counter++)
{
uhReaddata_16b = *(__IO uint16_t *)(Bank4_SDRAM_ADDR + 2 * counter); // 从该地址读出数据
if (uhReaddata_16b != (uint16_t)(uhWritedata_16b + counter)) // 检测数据,若不相等,跳出函数,返回检测失败结果。
{
// SDRAM_ERROR("16位数据读写错误!");
return 0;
}
}
/*检测正常,return 1 */
return 1;
}