欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

程序员文章站 2024-02-23 16:10:16
...

本篇详细的记录了如何使用STM32CubeMX配置 STM32F407ZGT6 的硬件FSMC外设与 SRAM 通信(IS62WV51216)。

1. 准备工作

硬件准备

  • 开发板
    首先需要准备一个开发板,这里我准备的是STM32F407ZGT6的核心板。

  • SRAM
    核心板板载一片SRAM,型号为 IS62WV51216,大小为 512K x 16 bit,也就是 1 MB。

STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

软件准备

需要准备一份 IS62WV51216 的数据手册。

2. STM32 FSMC外设概述

2.1. 什么是FSMC

FSMC全称 Flexible static memory controller,灵活的静态内存控制器,顾名思义,其主要作用是:负责向外部扩展的存储类设备提供控制信号

FSMC内存控制器支持的存储设备有:

  • Nor Flash、SRAM、PSRAM
  • Nand Flash
  • 类SRAM设备

2.2. FSMC外设的功能框图

STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

2.3. 外部设备的地址映射(重点)

从FSMC的角度来看,外部的存储设备被分为几个固定大小的Bank,每个bank 256 MB

整个FSMC外设映射地址的划分如图:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

2.3.1. Bank1

Bank1的地址空间为:0x6000 0000 - 0x6FFF FFFF,支持外接Nor Flash、PSRAM、SRAM等设备,还可以外接DM9000等类存储设备。

整个Bank1的地址空间被划分为四个子bank,每个子bank的大小为64MB,刚好对应FSMC外设的地址总线(FSMC_A[0:25])有26条(2^26=64MB)。

FSMC还有两条内部总线ADDR[27:26],用这两路控制片选信号,如下表:

STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

2.3.2. Bank2、3/4

只能外接Nand Flash设备和PC Card设备:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

3. 使用STM32CubeMX生成工程

选择芯片型号

打开STM32CubeMX,打开MCU选择器:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

搜索并选中芯片STM32F407ZGT6
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

配置时钟源

  • 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;
  • 如果使用默认内部时钟(HSI),这一步可以略过;

这里我都使用外部时钟:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

调试选项配置

默认没有配置下载引脚,烧录之后下载器将无法再检测到,这里我使用ST-Link,所以配置为SW选项:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

配置串口

开发板板载了一个CH340换串口,连接到USART1,但是引脚不是默认引脚,需要手动修改。

接下来开始配置USART1STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

配置FSMC外设

FSMC配置

开发板上SRAM(IS62WV51216)的原理图如下:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

通过原理图可以看出:

  • 数据总线位宽使用了16bit:FSMC D0 - FSMC D15;
  • 地址总线位宽使用了19bit:FSMC A0 - FSMC A18(地址线错乱为了方便PCB布线,实际使用时不影响);
  • 片选信号线:使用FSMC NE3,对应使用Bank1的Bank3子区域;
  • 通用信号线:FSMC NOE、FSMC NWE;
  • 数据掩码信号线:使用 FMC NBL0 和 FMC NBL1,分别控制输出高8位还是低8位;

根据这些信息,在STM32CubeMX中先配置SRAM3的基本设置:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

SRAM基本参数配置

这部分信息直接配置即可:STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

SRAM时序参数配置

通过之前的设置,SRAM的时钟频率为168Mhz,一个时钟周期就是5.95 ns,所以下面参数的单位都是5.95ns。

首先查看板载实际芯片最后的速度等级,这里我使用的是55ns这种:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)
① 地址建立时间:最大55ns,所以此项设置为1个HCLK。
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)
② 数据保持时间:最小10ns,这里设置为7个HCLK。
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

配置情况如下:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

配置时钟树

STM32F407ZGT6的最高主频到168M,使HCLK = 168Mhz即可:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

生成工程设置

STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

代码生成设置

最后设置生成独立的初始化文件:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

生成代码

点击GENERATE CODE即可生成MDK-V5工程:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

4. 测试SRAM读写

4.1. 重定向printf到串口1

/* USER CODE BEGIN 1 */
#if 1
#include <stdio.h>

int fputc(int ch, FILE *stream)
{
    /* 堵塞判断串口是否发送完成 */
    while((USART1->SR & 0X40) == 0);

    /* 串口发送完成,将该字符发送 */
    USART1->DR = (uint8_t) ch;

    return ch;
}
#endif
/* USER CODE END 1 */

具体参考这篇博客:STM32CubeMX_09 | 重定向printf函数到串口输出的多种方法

4.2. 编写SDRAM读写测试代码

接下来在main.c中添加SDRAM测试代码。

此测试代码来自安富莱电子。

① 引入 printf 头文件:

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

② 宏定义SRAM的映射地址以及SRAM的大小:

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
#define EXT_SRAM_ADDR  	    ((uint32_t)0x68000000)
#define EXT_SRAM_SIZE		(1 * 1024 * 1024)

uint32_t bsp_TestExtSRAM(void);
/* USER CODE END 0 */

③ 编写测试函数:

/* USER CODE BEGIN 4 */
/*
*********************************************************************************************************
*	函 数 名: bsp_TestExtSRAM
*	功能说明: 扫描测试外部SRAM的全部单元。
*	形    参: 无
*	返 回 值: 0 表示测试通过; 大于0表示错误单元的个数。
*********************************************************************************************************
*/
uint32_t bsp_TestExtSRAM(void)
{
	uint32_t i;
	uint32_t *pSRAM;
	uint8_t *pBytes;
	uint32_t err;
	const uint8_t ByteBuf[4] = {0x55, 0xA5, 0x5A, 0xAA};
	
	/* 写SRAM */
	pSRAM = (uint32_t *)EXT_SRAM_ADDR;
	for (i = 0; i < EXT_SRAM_SIZE / 4; i++)
	{
		*pSRAM++ = i;
	}
	
	/* 读SRAM */
	err = 0;
	pSRAM = (uint32_t *)EXT_SRAM_ADDR;
	for (i = 0; i < EXT_SRAM_SIZE / 4; i++)
	{
		if (*pSRAM++ != i)
		{
			err++;
		}
	}
	printf("SDRAM check round 1 error = %d\n", err);
	if (err > 0)
	{
		return (4 * err);
	}

	#if 1
	/* 对SRAM 的数据求反并写入 */
	pSRAM = (uint32_t *)EXT_SRAM_ADDR;
	for (i = 0; i < EXT_SRAM_SIZE/4; i++)
	{
		*pSRAM = ~*pSRAM;
		pSRAM++;
	}

	/* 再次比较SRAM的数据 */
	err = 0;
	pSRAM = (uint32_t *)EXT_SRAM_ADDR;
	for (i = 0; i<EXT_SRAM_SIZE/4;i++)
	{
		if (*pSRAM++ != (~i))
		{
			err++;
		}
	}

	printf("SDRAM check round 2 error = %d\n", err);
	if (err>0)
	{
	return (4 * err);
	}
	#endif

	/* 测试按字节方式访问, 目的是验证 FSMC_NBL0 、 FSMC_NBL1 口线 */
	pBytes = (uint8_t *)EXT_SRAM_ADDR;
	for (i = 0; i < sizeof(ByteBuf); i++)
	{
		*pBytes++ = ByteBuf[i];
	}

	/* 比较SRAM的数据 */
	err = 0;
	pBytes = (uint8_t *)EXT_SRAM_ADDR;
	for (i = 0; i < sizeof(ByteBuf); i++)
	{
		if (*pBytes++ != ByteBuf[i])
		{
			err++;
		}
	}
	printf("SDRAM check round 3 error = %d\n", err);
	if (err > 0)
	{
		return err;
	}
	return 0;
}

/* USER CODE END 4 */

④ 在main函数中调用:

/* USER CODE BEGIN 2 */
  printf("STM32F407ZG FSMC SRAM Test By Mculover666\r\n");

  if (bsp_TestExtSRAM() == 0) {
      printf("SRAM Test success\r\n");
  } else {
      printf("SRAM Test fail\r\n");
  }
/* USER CODE END 2 */

4.3. 实验结果

编译,下载到开发板中,在串口助手中查看实验结果:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

5. 直接指定变量存储到 SRAM 空间

第4节中的测试方法是使用指针访问SRAM空间,未免过于麻烦。在实际使用中,可以直接定义一个非常大的数组,将整个数组都存储到SRAM上,然后动态的使用SRAM内存空间。

要注意使用这种方法定义变量时,必须在函数外把它定义成全局变量,才可以存储到指定地址上。

测试过程如下:

① 定义全局变量并指定绝对地址:

/* 绝对定位方式访问 SDRAM,这种方式必须定义成全局变量 */
uint8_t testValue __attribute__((at(EXT_SRAM_ADDR)));

② 在main函数中赋值,然后打印:

/* 操作在SRAM的变量 */
testValue = 0x5a;
printf("testValue is %#x\r\n", testValue);

编译,下载,查看实验结果:
STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)

更多精彩文章及资源,请关注我的微信公众号:『mculover666』。

STM32CubeMX | 34-使用硬件FSMC读写SRAM(IS62WV51216)