GD32学习笔记(1)EXMC介绍

AHB总线

       在介绍EXMC前,首先简要地介绍一下AHB总线,处理器通过总线与其它设备进行数据交换,以GD32F303ZET6微控制器为例,其AHB总线架构如下图所示,而EXMC通过AHB总线与处理器连接。
在这里插入图片描述

EXMC简介

       EXMC:External Memory Controller,即外部存储器控制器,其功能与stm32微控制器的FSMC相同,GD32系列微控制器通过EXMC访问SRAM、 NAND FLASH等存储器,通过将存储器的空间映射到相应的地址来完成控制。

EXMC原理

       由AHB总线架构一图得,EXMC与AHB总线连接,而另一端,EXMC与外部存储器相连,此时处理器才可以通过总线与外部存储器进行数据交换。

       以32位AHB总线为例,可控制的最大存储器空间为2^32=4GB,而这4GB地址的分配可以参照用户手册中的存储器映射表:(不是全部都用来进行地址映射,0xA000 0FFF大约为2.5G)
在这里插入图片描述

EXMC空间分配

       如下图所示,EXMC的空间范围为0x6000 0000~0x9FFF FFFF,这些空间被分为4个Bank,每个Bank为256M,支持不同的存储器类型。
在这里插入图片描述
       每个Bank有根据功能进行划分,以Bank0为例,Bank0被分为4个区域,每个区域大小为64M。

SRAM只能被连接到 Bank0,当然不同存储器在Bank上的不同只会显示在代码上,硬件上都是连接到引脚名称为EXMC_xx上。当然,Region则不同,比如SRAM可以连接到4个Region上,而具体连接到哪个Region,则要看硬件上存储器芯片的片选引脚与MCU引脚的连接,如果和EXMC_NE2,那么初始化的时候就应该选择Region2进行初始化(如下面的代码,硬件上连接的是NE1引脚,那么就选择Region1)

EXMC与AHB的连接

       将32位AHB总线用A[32:0]表示,其中对于EXMC,A[27:26]用于选中Bank0不同的region,A[25:0]用于确定存储器具体的地址,2^26=64M,可以确定大小为64MB大小的空间。(即1个地址值确定1字节的值)

       当存储器为16位宽,即1个地址值确定2个字节的值时,A[25:1]对应外部存储器的[24:0],(处理器通过EXMC控制外设,那么外设肯定也要有EXMC接口,而64MB大小,16位宽的存储器只需要[24:0],此时A[25]不需要控制)当存储器为8位宽,即1个地址值确定1个字节的值时,A[25:0]对应外部存储器的[25:0]。

1个地址值确定1个字节的值的意思是,将空间分为小空间,每个空间的大小为1字节,通过相应的地址值即可控制对应的空间,这样每个地址值对应1字节,可以通过指针等手段完成向相应地址的空间写入、读取值等操作。

AHB总线分配

       那看到这里,很明显有一个问题,32位AHB总线的其它位用来干嘛?A[31:28]好像没看到介绍?那是不是A[29:28]用来确定4个Bank,而A[31:30]用来确定本文第一张图中包括EXMC对应的4个从机?好像这样解释完全合理,但很遗憾,这是错误的!

       这部分问题可以看到本文的第二张图,存储器的映射表,A[31:0]实际上就是存储器的地址范围(上面也说到,不是所有的都分配在这里,只有大概2.5G在),当A[31:0]各个位有了具体的二进制值,则可以换算为16进制再检查数据是否位于下面的地址范围中。

       因此,“A[27:26]用于选中Bank0不同的region”仅仅是因为当A[31:28]确定时,A[27:26]刚好与4个区域对应。

在这里插入图片描述

注意

       EXMC和FSMC的作用都是控制存储器,作为片内外设,通过芯片引脚与存储器连接,因此,从代码来看,EXMC仅仅是引脚的一种功能,使用时仅需要初始化引脚后使能其EXMC功能,最后通过代码在相应地址上写入数据即可完成对存储器的写入。

       以初始化EXMC的Bank0Region1为例(相应引脚的初始化在另一函数):

static void ConfigBank0Region1(void)
{
  exmc_norsram_parameter_struct        sram_init_struct;
  exmc_norsram_timing_parameter_struct lcd_readwrite_timing_init_struct;
  exmc_norsram_timing_parameter_struct lcd_write_timing_init_struct;

  //使能EXMC时钟
  rcu_periph_clock_enable(RCU_EXMC);

  //读时序配置
  lcd_readwrite_timing_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A; //模式A,异步访问SRAM
  lcd_readwrite_timing_init_struct.asyn_address_setuptime = 0;  //异步访问地址建立时间
  lcd_readwrite_timing_init_struct.asyn_address_holdtime  = 0;  //异步访问地址保持时间
  lcd_readwrite_timing_init_struct.asyn_data_setuptime    = 15; //异步访问数据建立时间
  lcd_readwrite_timing_init_struct.bus_latency            = 0;  //同步/异步访问总线延时时间
  lcd_readwrite_timing_init_struct.syn_clk_division       = 0;  //同步访问时钟分频系数(从HCLK中分频)
  lcd_readwrite_timing_init_struct.syn_data_latency       = 0;  //同步访问中获得第1个数据所需要的等待延迟

  //写时序配置
  lcd_write_timing_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A; //模式A,异步访问SRAM
  lcd_write_timing_init_struct.asyn_address_setuptime     = 0; //异步访问地址建立时间
  lcd_write_timing_init_struct.asyn_address_holdtime      = 0; //异步访问地址保持时间
  lcd_write_timing_init_struct.asyn_data_setuptime        = 2; //异步访问数据建立时间
  lcd_write_timing_init_struct.bus_latency                = 0; //同步/异步访问总线延时时间
  lcd_write_timing_init_struct.syn_clk_division           = 0; //同步访问时钟分频系数(从HCLK中分频)
  lcd_write_timing_init_struct.syn_data_latency           = 0; //同步访问中获得第1个数据所需要的等待延迟

  //Region1配置
  sram_init_struct.norsram_region    = EXMC_BANK0_NORSRAM_REGION1; //Region1
  sram_init_struct.address_data_mux  = DISABLE;                    //禁用地址、数据总线多路复用
  sram_init_struct.memory_type       = EXMC_MEMORY_TYPE_SRAM;      //储存器类型为SRAM
  sram_init_struct.databus_width     = EXMC_NOR_DATABUS_WIDTH_16B; //数据宽度16位
  sram_init_struct.burst_mode        = DISABLE;                    //禁用突发访问
  sram_init_struct.nwait_config      = EXMC_NWAIT_CONFIG_BEFORE;   //等待输入配置
  sram_init_struct.nwait_polarity    = EXMC_NWAIT_POLARITY_LOW;    //等待输入信号低电平有效
  sram_init_struct.wrap_burst_mode   = DISABLE;                    //禁用包突发访问
  sram_init_struct.asyn_wait         = DISABLE;                    //禁用异步等待
  sram_init_struct.extended_mode     = ENABLE;                     //使能扩展模式
  sram_init_struct.memory_write      = ENABLE;                     //使能写入外部存储器
  sram_init_struct.nwait_signal      = DISABLE;                    //禁用等待输入信号
  sram_init_struct.write_mode        = EXMC_ASYN_WRITE;            //写入模式为异步写入
  sram_init_struct.read_write_timing = &lcd_readwrite_timing_init_struct; //读时序配置
  sram_init_struct.write_timing      = &lcd_write_timing_init_struct;     //写时序配置

  //初始化Region1
  exmc_norsram_init(&sram_init_struct);

  //使能Region1
  exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION1);
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值