GD32F470系列1:调用EXMC与FPGA通信实例-FPGA常见问题论坛-FPGA CPLD-ChipDebug

GD32F470系列1:调用EXMC与FPGA通信实例

 

 


一、EXMC简介

EXMC是GD32单片机系列的外部并行总线接口,用来访问各种片外存储器,通过配置寄存器,EXMC可以把AMBA协议转换为专用的片外存储器通信协议,包括SRAM,ROM,NOR Flash,NAND Flash,PC Card和SDRAM。用户还可以调整相关的时间参数来提高通信效率。EXMC的访问空间被划分为许多个块(Bank),每个块支持特定的存储器类型,用户可以通过对Bank的控制寄存器配置来控制外部存储器。


本文采用EXMC的异步通信模式A配置供作参考

二、EXMC区域划分及region划分

EXMC区域划分
在本文博客中才使用的是Bank0。下面则是该bank内Region的划分。在该文中我们采用NOR/PSRAM0M存储器类型去控制,该模式最为方便控制。该区域对应Region为Region0。对应操作寄存器地址为0x60000000—0x63ff ffff。
Bank0区域region划分
在该处,程序配置的寄存器类型一定要跟Region匹配,否则没法正常读写。

三、读写时序图

在该部分采用的是异步通信的模式A,其主要控制线为ne0(1,2,3),nwe, noe。我们后面在FPGA端解析协议时也是靠这几根线的变化去判断控制。

1.模式A读时序控制

模式A读时序
在读时序中可以看到,NEx信号在单次传输中保持为低电平,而读操作时 NOE信号线在传输后半段时间拉低,并在此时间读取数据线上数据。FPGA端则可以将这两根信号线的同时低电平作为判决条件往数据线上放数据。

2.模式A写时序控制

模式A写时序
写时序与读类似,只是NWE在写操作过程中拉低。

3.寄存器配置

1. 需配置寄存器

该部分为模式A时EXMC寄存器配置

/* EXMC NOR/SRAM initialize structure */
typedef struct
{
    uint32_t norsram_region;  
    /*选择读写区域,可选:EXMC_BANK0_NORSRAM_REGIONx, x=0..3 */
    uint32_t write_mode; 
    /*同步/异步写入模式控制 
    异步EXMC_ASYN_WRITE, 同步EXMC_SYN_WRITE */
    uint32_t extended_mode;                                  
    /*是否是能扩展模式,即使能EXMC_SNWTCFGx,此处未使能*/
    /*若使能扩展模式则可通过通过寄存器
    EXMC_SNTCFGx和EXMC_SNWTCFGx将读写配置成独立的时序*/
    uint32_t asyn_wait;   
    /*是否使能异步等待 */
    uint32_t nwait_signal;  
    /*等待输入信号使能 */
    uint32_t memory_write;                           
    /*写入外部存储器使能 */
    uint32_t nwait_config;                                  
    /*等待输入配置, 
    EXMC_NWAIT_CONFIG_BEFORE, EXMC_NWAIT_CONFIG_DURING*/
    uint32_t wrap_burst_mode;                                  
    /*包突发访问使能 */
    uint32_t nwait_polarity;                                 
    /*等待输入信号高低电平有效控制,
    EXMC_NWAIT_POLARITY_LOW, EXMC_NWAIT_POLARITY_HIGH */
    uint32_t burst_mode;                             
    /*突发模式使能 */
    uint32_t databus_width;                           
    /*数据传输宽度设置,可选8/16位
    EXMC_NOR_DATABUS_WIDTH_8B, EXMC_NOR_DATABUS_WIDTH_16B */
    uint32_t memory_type;     
    /*寄存器类型  EXMC_MEMORY_TYPE_SRAM, 
    EXMC_MEMORY_TYPE_PSRAM, EXMC_MEMORY_TYPE_NOR */
    uint32_t address_data_mux;        
    /*地址数据线是否复用*/
    
    exmc_norsram_timing_parameter_struct* read_write_timing;       
    /*若使能扩展模式,此结构体则为读模式时序控制;若未使能,则为读写时序统一设置 */
    exmc_norsram_timing_parameter_struct* write_timing;        
    /*使能拓展模式时写时序控制 */
}exmc_norsram_parameter_struct;

 

时序控制参数

/* EXMC NOR/SRAM timing initialize structure */
typedef struct
{
    uint32_t asyn_access_mode;                      
    /*异步地址访问时间 */
    uint32_t syn_data_latency;                      
    /*同步访问中获得第一个数据所需要的等待延迟 */
    uint32_t syn_clk_division;                          
    /*同步访问时钟分频系数(从HCLK中分频) */
    uint32_t bus_latency;               
    /*!< 访问总线延迟时间 */
    uint32_t asyn_data_setuptime;                              
    /*异步数据建立时间 */
    uint32_t asyn_address_holdtime;                              
    /*异步地址保持时间 */
    uint32_t asyn_address_setuptime;        
    /*异步地址建立时间 */
}exmc_norsram_timing_parameter_struct;

 

该处均需配置,根据是否使能拓展模式是否对读写单独配置。

2. 配置程序参考

exmc_norsram_parameter_struct norsram_init_struct;
exmc_norsram_timing_parameter_struct norsram_timing_init_struct;
//结构体重构

		rcu_periph_clock_enable(RCU_EXMC);                                                                  
		rcu_periph_clock_enable(RCU_GPIOD);
		rcu_periph_clock_enable(RCU_GPIOE);
		rcu_periph_clock_enable(RCU_GPIOB);
//时钟使能,后把相关引脚都使能,此处不详写		
		
		norsram_timing_init_struct.asyn_address_setuptime = 9;
		//地址建立时间
		norsram_timing_init_struct.asyn_address_holdtime = 1;
		//地址保持时间
		norsram_timing_init_struct.asyn_data_setuptime = 8;
		//数据建立时间
		norsram_timing_init_struct.bus_latency = 0;
		//总线延迟
		norsram_timing_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK;
		//此处同步访问时钟分频系数,实测即使异步模式也不能设置为0
		norsram_timing_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;
		//同步数据等待延迟
		norsram_timing_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;

 

读写时序参数参考

norsram_init_struct.norsram_region = EXMC_BANK0_NORSRAM_REGION0;
		//使用 region 0
		norsram_init_struct.address_data_mux = ENABLE;
		//使能地址数据复用,也可以不复用
		norsram_init_struct.memory_type = EXMC_MEMORY_TYPE_NOR;
		//存储器类型设置为NOR,我测试时SRAM不能用
		norsram_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
		norsram_init_struct.burst_mode = DISABLE;
		//禁用突发模式
		norsram_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
		//等待信号低有效
		norsram_init_struct.wrap_burst_mode = DISABLE;
		//禁止包突发
		norsram_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
		norsram_init_struct.memory_write = ENABLE;
		norsram_init_struct.nwait_signal = DISABLE;
		norsram_init_struct.extended_mode = DISABLE;
		norsram_init_struct.asyn_wait = DISABLE;
		norsram_init_struct.write_mode = EXMC_ASYN_WRITE;

 

3. 读写时操作地址范例

void FSMC_SRAM_ReadBuffer_single(uint16_t* pBuffer)
{
		for(j=0;j<12288;j++){
			if(flag){
				*pBuffer += *(uint16_t*) (0x60000000); }
			else{
				*pBuffer = *(uint16_t*) (0x60000000);		
			}
			pBuffer++;	
		}		
}

 

此处代码功能为向Bank0—Region0 读取数据12288次,在读取中为固定地址读取,减小引脚变化以节省损耗。


总结

EXMC相比于FSMC基本上完全一致,有啥问题也可以在评论区一起讨论。‘

 

请登录后发表评论

    没有回复内容