[研电赛技术支持] 【GD32F303红枫派使用手册】第二十五讲 EXMC-外部SRAM读写实验

[复制链接]
3767|0
 楼主| 聚沃科技 发表于 2024-6-25 09:31 | 显示全部楼层 |阅读模式
红枫派首图.png
25.1 实验内容
通过本实验主要学习以下内容:
• EXMC外设原理和配置
• EXMC NOR/SRAM模式介绍
外部SRAM接口时序和操作方式
25.2 实验原理
MCU的片内SRAM空间有限,在做一些大量数据处理、GUI显示等应用中片内SRAM容量无法满足应用需求,而外部SRAM器件读写速度快,不需要自刷新,工作稳定,是性能最优的外扩RAM选择之一。MCU通过EXMC接口可以实现外部SRAM的接口通信协议,同时可映射到内部地址实现和内部ram相同的操作方式。
25.2.1 EXMC外设原理
EXMCMCU的外部存储控制器,可以配置实现各类片外设备的通信协议,包括SRAMPSRAMNOR FLASHNAND FLASH等,也可以通过配置实现一些其他通信协议,如8080接口的LCD驱动、FPGA通信等,可灵活的实现很多异步同步信号输入输出,时序时间可配置。更重要的是EXMC可通过地址映射方式实现MCU内部总线协议到外部器件通信的转换,实现高效的数据读取和输出能力。
• EXMC系统架构如下图所示,外部SRAM使用NOR-Flash/PSRAM控制器实现通信协议,使用NWENOEEXMC_DxEXMC_AxEXMC_NBLxEXMC_NEx引脚和SRAM器件进行连接。
图片9.png
EXMC根据不同存储器类型,对应有4BANK,每个BANK256MB占用了不同地址空间。访问对应BANK区的地址时EXMC会自动按对应改区存储类型的时序和配置进行通信。
图片10.png
25.2.2 EXMC NOR/SRAM模式介绍
SRAM/NOR类型对应区域为BANK0总计256MB空间。而BANK0其中有分了4Regions64MB,每个Regions分别对应NE0——NE4引脚连接的器件,可以连接464MB SRAM就可以组成256MB的连续SRAM地址空间,也可以连接4NOR或者2NOR2SRAM的组合方式。
图片11.png
访问外部SRAM时,采用了EXMC SRAM异步访问模式A,读写开始时NE先拉低,接着地址先建立并保持,同时其他信号根据当前访问方向等进行信号对应输出,接下来MCU或器件输出数据信号建立,在输出使能的边沿进行采样,读写结束NE拉高。读写信号时序如下图:
图片12.png
在这个时序过程中,很多参数可以进行配置调节,其中主要是地址建立和保持、数据建立的参数,一般根据速率要求、硬件信号斜率限制来平衡这个参数,目标为达到一个满足稳定性的最高速率参数。相关参数如下表所示:
图片13.png
25.2.3 外部SRAM器件原理
sram存储模型可以使用下图说明:
图片14.png
SRAM内部包含的存储阵列,和表格查找一样,指定一个行地址和列地址,就可以精确地找到目标BIT单元格,这是SRAM芯片寻址的基本原理。这样的每个单元格被称为存储单元,而这样的表则被称为存储矩阵。地址译码器把N根地址线转换成2N次方根信号线,每根信号线对应一行或一列存储单元,通过地址线找到具体的存储单元,实现寻址。如果存储阵列比较大,地址线会分成行和列地址,或者行、列分时复用同一地址总线,访问数据寻址时先用地址线传输行地址再传输列地址。
在外部SRAM上,列地址对应了数据宽度,如例程所用的IS62WV51216BLL16位宽度,故而行地址范围是19,对应了IS62WV51216BLLA0-A19引脚,主控芯片通过A0-A19引脚即可实现对行地址进行寻址访问到对应的16BIT数据。
如下图所示为外部SRAM接口信号,主控通过特定接口按时序即可时序地址发送、数据发送和读取,实现对指定地址数据的读写。
图片15.png
25.3 硬件设计
如下是IS62WV51216BLL的原理图设计,MCU通过EXMC相关对应接口连接到SRAM
图片16.png
• SRAM作为敏感器件,需要保证电源的稳定、减少噪声,串接了磁珠后供电,同时对sramvdd引脚必须就近放置0.1uf去耦电容,若整个系统中存在较多其他负载,可以再增加较大电容稳定电源。
• SRAMCS引脚通过MCU EXMC_NEx引脚控制,由于片选信号较为关键,避免MCUEXMC多器件时悬空信号不稳定导致误操作,需要增加上拉电阻;在这里,上拉电阻应当靠近SRAM放置,减少连接回路上的耦合干扰。
25.4 代码解析
EXMC在初始化后,基本上通过程序的地址映射就可以进行操作了,需要根据外部器件的要求进行exmc相关参数配置,exmc可配置参数有很多,但选定好一个模式后实际在这个模式下需要配置的参数是有限的,一些结构体成员只需要按默认参数配置即可。
25.4.1 EXMC SRAM模式初始化
sram访问时,可能会调整的exmc参数如下:
图片17.png
其中数据建立、地址建立、地址保持三个参数尤其关键,影响到最终的速率以及稳定性,需要根据器件、电路设计、PCB设计、信号测试综合来调试选取合适的值;其单位为AHB CLK
图片18.png
整个SRAM配置过程主要包含:GPIOEXMC外设接口时钟、GPIO配置、EXMC相关参数配置,完整代码如下:
  1. C
  2. /*!
  3. * 说明     emxc nor/sram模式初始化
  4. * 输入[1]  norsram_region: @EXMC_BANK0_NORSRAM_REGION0/EXMC_BANK0_NORSRAM_REGION1/EXMC_BANK0_NORSRAM_REGION2/EXMC_BANK0_NORSRAM_REGION3
  5. * 返回值   无
  6. */
  7. void driver_exmc_sram_init(uint32_t norsram_region)
  8. {
  9.     exmc_norsram_parameter_struct nor_init_struct;
  10.     exmc_norsram_timing_parameter_struct nor_timing_init_struct;

  11.     /* EXMC clock enable */
  12.     rcu_periph_clock_enable(RCU_EXMC);

  13.     /* EXMC enable */
  14.     rcu_periph_clock_enable(RCU_GPIOB);
  15.     rcu_periph_clock_enable(RCU_GPIOD);
  16.     rcu_periph_clock_enable(RCU_GPIOE);
  17.     rcu_periph_clock_enable(RCU_GPIOF);
  18.     rcu_periph_clock_enable(RCU_GPIOG);

  19.     /* configure EXMC_D[0~15]*/
  20.     /* PD14(EXMC_D0), PD15(EXMC_D1),PD0(EXMC_D2), PD1(EXMC_D3), PD8(EXMC_D13), PD9(EXMC_D14), PD10(EXMC_D15) */
  21.     gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |
  22.                                                          GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

  23.     /* PE7(EXMC_D4), PE8(EXMC_D5), PE9(EXMC_D6), PE10(EXMC_D7), PE11(EXMC_D8), PE12(EXMC_D9),
  24.        PE13(EXMC_D10), PE14(EXMC_D11), PE15(EXMC_D12) */
  25.     gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |
  26.                                                          GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
  27.                                                          GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  28.                                                             

  29.     /* configure NBL0(PE0) and NBL1(PE1) */
  30.     gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_9 | GPIO_PIN_10);
  31.    
  32.     /* configure NBL0(PE0) and NBL1(PE1) */
  33.     gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
  34.    
  35.     exmc_norsram_struct_para_init(&nor_init_struct);
  36.    
  37.     /* config timing parameter */
  38.     nor_timing_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;
  39.     nor_timing_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;
  40.     nor_timing_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_2_CLK;
  41.     nor_timing_init_struct.bus_latency = 0;
  42.     nor_timing_init_struct.asyn_data_setuptime = 8;
  43.     nor_timing_init_struct.asyn_address_holdtime = 8;
  44.     nor_timing_init_struct.asyn_address_setuptime = 8;

  45.     /* config EXMC bus parameters */
  46.     nor_init_struct.norsram_region = norsram_region;
  47.     nor_init_struct.write_mode = EXMC_ASYN_WRITE;
  48.     nor_init_struct.extended_mode = DISABLE;
  49.     nor_init_struct.asyn_wait = DISABLE;
  50.     nor_init_struct.nwait_signal = DISABLE;
  51.     nor_init_struct.memory_write = ENABLE;
  52.     nor_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
  53.     nor_init_struct.wrap_burst_mode = DISABLE;
  54.     nor_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
  55.     nor_init_struct.burst_mode = DISABLE;
  56.     nor_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
  57.     nor_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM;
  58.     nor_init_struct.address_data_mux = DISABLE;
  59.     nor_init_struct.read_write_timing = &nor_timing_init_struct;
  60.     nor_init_struct.write_timing = &nor_timing_init_struct;
  61.     exmc_norsram_init(&nor_init_struct);

  62.     /* enable the EXMC bank0 NORSRAM */
  63.     exmc_norsram_enable(norsram_region);   
  64. }
25.4.2 初始化调用
红枫派开发板中SRAMCS连接引脚为EXMC_NE0引脚,故而对应EXMC BANK0 Region0区,调用初始化时我们传入参数EXMC_BANK0_NORSRAM_REGION0即可。
  1. C
  2.     //初始化exmc norsram region0
  3.     driver_exmc_norsram_init(EXMC_BANK0_NORSRAM_REGION0);
25.4.3 地址映射访问方式
初始化好后EXMC BANK0 Region0区的地址可以理解就和外部SRAM形成了映射关系,读写这些地址时EXMC会先拉低NE0选择SRAM进行通信和交互;
○ exmc驱动的头文件中定义好了BANK4Region地址,我们对Region0地址读写即可实现外部SRAM的数据读写。
图片19.png
同样我们也可以直接在编译器里定义外部sram地址范围,直接让编译器把定义的变量和数组放在外部sram中,我们不用再关心其具体地址;但我们需要在main函数之前初始化好exmc,可以在启动文件中调用exmc初始化。
图片20.png
图片21.png
25.4.4 main函数设计
mian函数中通过指针方式以8位、16位、32位写并读取校验了外部SRAM数据
  1. C
  2. int main(void)
  3. {   
  4.     uint32_t writereadstatus = 0;   
  5.    
  6.     //延时和公共驱动部分初始化
  7.     driver_init();

  8.     //打印串口初始化   
  9.     bsp_uart_init(&BOARD_UART);
  10.    
  11.     //初始化LED组   
  12.     bsp_led_group_init();  
  13.     bsp_led_off(&LED0);
  14.     bsp_led_off(&LED1);
  15.    
  16.     //初始化exmc norsram region0
  17.     driver_exmc_norsram_init(EXMC_BANK0_NORSRAM_REGION0);
  18.    
  19.     delay_ms(100);
  20.     printf("External sram read and write examples.\r\n");   
  21.    
  22.          
  23.     //以32位读写校验   
  24.     printf("32-bit read/write check.\r\n");
  25.     writereadstatus=0;   
  26.     for(uint32_t index = 0; index < EXMC_SRAM_SIZE; index++ ){
  27.         REG32(EXMC_BANK0_NORSRAM_REGION0_ADDR+index*4)=0xa55aa55a;
  28.     }
  29.     for(uint32_t index = 0; index < EXMC_SRAM_SIZE; index++ ){
  30.         if(0xa55aa55a!=REG32(EXMC_BANK0_NORSRAM_REGION0_ADDR+index*4)){
  31.             writereadstatus++;
  32.             break;
  33.         }
  34.     }
  35.     if(writereadstatus){
  36.         bsp_led_on(&LED0);
  37.         printf("\r\n32-bit read/write SRAM test failed!");
  38.     }else{
  39.         bsp_led_on(&LED1);
  40.         printf("\r\n32-bit read/write SRAM test successed!");
  41.     }
  42.    
  43.    
  44.     //以16位读写校验
  45.     printf("16-bit read/write check.\r\n");
  46.     writereadstatus=0;   
  47.     for(uint32_t index = 0; index < EXMC_SRAM_SIZE; index++ ){
  48.         REG16(EXMC_BANK0_NORSRAM_REGION0_ADDR+index*2)=0xaaaa;
  49.     }
  50.     for(uint32_t index = 0; index < EXMC_SRAM_SIZE; index++ ){
  51.         if(0xaaaa!=REG16(EXMC_BANK0_NORSRAM_REGION0_ADDR+index*2)){
  52.             writereadstatus++;
  53.             break;
  54.         }
  55.     }
  56.     if(writereadstatus){
  57.         bsp_led_on(&LED0);
  58.         printf("\r\n16-bit read/write SRAM test failed!");
  59.     }else{
  60.         bsp_led_on(&LED1);
  61.         printf("\r\n16-bit read/write SRAM test successed!");
  62.     }

  63.    
  64.     //以8位读写校验
  65.     printf("8-bit read/write check.\r\n");
  66.     writereadstatus=0;   
  67.     for(uint32_t index = 0; index < EXMC_SRAM_SIZE; index++ ){
  68.         REG8(EXMC_BANK0_NORSRAM_REGION0_ADDR+index)=0x55;
  69.     }
  70.     for(uint32_t index = 0; index < EXMC_SRAM_SIZE; index++ ){
  71.         if(0x55!=REG8(EXMC_BANK0_NORSRAM_REGION0_ADDR+index)){
  72.             writereadstatus++;
  73.             break;
  74.         }
  75.     }
  76.     if(writereadstatus){
  77.         bsp_led_on(&LED0);
  78.         printf("\r\n8-bit read/write SRAM test failed!");
  79.     }else{
  80.         bsp_led_on(&LED1);
  81.         printf("\r\n8-bit read/write SRAM test successed!");
  82.     }     
  83.       
  84.         while (1)
  85.         {

  86.         
  87.         }
  88. }
25.5 实验结果
连接USB转串口,将打印读写校验结果。

本教程由GD32 MCU方案商聚沃科技原创发布,了解更多GD32 MCU教程,关注聚沃科技官网,GD32MCU技术交流群:859440462


您需要登录后才可以回帖 登录 | 注册

本版积分规则

170

主题

190

帖子

13

粉丝
快速回复 在线客服 返回列表 返回顶部