8139 views|4 replies

291

Posts

5

Resources
The OP
 

【GD32450I-EVAL】+ 06SDRAM Introduction [Copy link]

This post was last edited by DDZZ669 on 2020-10-4 17:28

1 SDRAM

RAM can be understood as memory, the space required by the program when running. GD32F450IK comes with 256K RAM. When a large memory is needed, it is necessary to expand the RAM. This development board is equipped with an MT48LC16M16A2P SDRAM.

1.1 Basic Principles of SDRAM Data Storage

The SDRAM model on the board is: MT48LC16M16A2P-6AIT, and its schematic diagram is as follows:

The function of each pin is shown in the following table:

SDRAM is divided into multiple areas called banks, which allow devices to access them in an interleaved manner to obtain greater concurrency and data transfer. Each bank can be considered as a matrix, where each address corresponds to the space of the memory storage width. The matrix consists of rows and columns, so the bank size of the memory can be considered as the number of rows and columns of the memory data width.

As shown in the figure below, for this storage array, we can regard it as a table. We only need to give the row address and column address to determine its unique location. This is the basic principle of SDRAM addressing. There are generally 4 such storage units (BANK0~BANK3) inside an SDRAM chip. Therefore, when addressing inside the SDRAM, first specify the BANK number and row address, and then specify the column address to find the target address.

When SDRAM is addressed:

1 First, the RAS signal is low, the row address is selected, and the address represented by the address lines A0~A12 will be transmitted and latched into the row address decoder as the row address.

2 At the same time, the BANK addresses represented by BS0 and BS1 on the BANK address lines will also be latched, and the corresponding BANK will be selected.

3 Then, the CAS signal is low, the column address is selected, and the address represented by the address lines A0~A12 will be transmitted and latched into the column address decoder as the column address.

In this way, one addressing is completed.

1.2 Analysis of Onboard SDRAM Models

Let's take a look at the meaning of the naming of the MT48LC16M16A2P-6AIT model. You can check its data sheet:

Here are some more tables:

The storage structure of MT48LC16M16A2P-6AIT is:

  • Row address: 8192 (8K)
  • Column address: 512
  • Number of banks: 4
  • Bit width: 16 bits

In this way, the capacity of the entire chip is 8192*512*4*16=32M bytes.

1.3 SDRAM Control Logic

A series of commands are required to control SDRAM, and various signal line state combinations produce different control commands.

Due to the volatile nature of data, SDRAM needs to be refreshed periodically. EXMC supports two refresh modes, self-refresh and auto-refresh. Self-refresh is used in the low-power mode when EXMC is suspended. The clock is provided by the internal count of SDRAM and refresh is performed internally. Auto-refresh is when EXMC periodically provides refresh commands, because SDRAM needs to transfer data at this time. The refresh interval is determined by the register EXMC_SDARI bit ARINTV, and the number of consecutive refreshes is determined by the register EXMC_SDCMD bit NARF.

DRAM cannot start reading and writing data immediately after power-on. It needs to be initialized step by step to precharge the storage matrix, refresh it, and set the mode register, etc.

SDRAM initialization process:

  • Power on

Power the SDRAM and enable the CLK clock. Note that after powering on, wait for at least 200us before sending other commands.

  • Send NOP

Send NOP (No Operation Command)

  • Send PRECHARGE

Send a precharge command to precharge all banks.

  • Send AUTO REFRESH

At least 8 self-refresh commands must be sent, and the interval between each self-refresh command is tRFC.

  • Setting LOAD MODE REGISTER

Send the value of the mode register to configure the working parameters of the SDRAM. After the configuration is completed, you need to wait for tMRD (also called tRSC) for the configuration of the mode register to take effect before sending other commands.

  • Finish

After the previous operations, the initialization of SDRAM is completed. Next, you can send activation commands and read/write commands to read/write data.

2 EXMC

GD32's external memory controller EXMC is used to access various off-chip memories. By configuring registers, EXMC can convert the AMBA protocol into a dedicated off-chip memory communication protocol, including SRAM, ROM, NOR Flash, NAND Flash, PC Card and SDRAM. Users can also adjust related time parameters to improve communication efficiency. The EXMC module is divided into many sub-Banks, each Bank supports a specific memory type, and users can control the external memory by configuring the Bank's registers.

EXMC consists of 6 modules: AHB bus interface, EXMC configuration register, NOR/PSRAM controller, NAND/PC Card controller, SDRAM controller and external device interface. AHB clock HCLK is the reference clock.

EXMC divides the external memory into multiple banks, each bank occupies 256M bytes, of which Bank0 is divided into 4 regions, each region occupies 64M bytes. Bank1 and Bank2 are divided into 2 sections, namely attribute storage space and general storage space. Bank3 is divided into 3 sections, namely attribute storage space, general storage space and I/O storage space. Each bank and region has an independent chip select control signal and can be configured independently.

  • Bank0 is used to access NOR and PSRAM devices.
  • Bank1 and Bank2 are used to connect NAND Flash, and each Bank is connected to one NAND.
  • Bank3 is used to connect PC card.
  • SDRAM Device0 and SDRAM Device1 are used to connect SDRAM.

EXMC divides the SDRAM storage area into two blocks: device0 and device01. The SDRAM address mapping is as follows:

3 Program Analysis

Let's take a look at the SDRAM routine. First, the main function:

int main(void)
{
    uint16_t i = 0;

    /* LED initialize */
    gd_eval_led_init(LED1);
    gd_eval_led_init(LED3);
    
    /* systick clock configure */
    systick_config();
    
    /* config the USART */
    gd_eval_com_init(EVAL_COM1);
	
	/* fill txbuffer */
    fill_buffer(txbuffer, BUFFER_SIZE, 0x0000);
    
	//===============SDRAM初始化===================
    /* config the EXMC access mode */
    exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0);//SDRAM device0: 0x00000004U
    
    printf("\r\nSDRAM initialized!");
    delay_1ms(1000);
    
	//===============写入SDRAM===================
    printf("\r\nSDRAM write data...");
    delay_1ms(1000);
    
    /* write data to SDRAM */
    sdram_writebuffer_8(EXMC_SDRAM_DEVICE0,txbuffer, WRITE_READ_ADDR, BUFFER_SIZE);
    
	//===============读取SDRAM===================
    printf("\r\nSDRAM read data...");
    delay_1ms(1000);
    
    /* read data from SDRAM */
    sdram_readbuffer_8(EXMC_SDRAM_DEVICE0,rxbuffer, WRITE_READ_ADDR, BUFFER_SIZE);
    
	//===============检查写入与读出的是否相同===================
    printf("\r\nCheck the data!");
    delay_1ms(1000);
    
    /* compare two buffers */
    for(i = 0;i < BUFFER_SIZE;i++)
	{
        if (rxbuffer[i] != txbuffer[i])
		{
            writereadstatus ++;
            break;
        }
    }

    if(writereadstatus)
	{
        printf("\r\nSDRAM test failed!");

        /* failure, light on LED3 */
        gd_eval_led_on(LED3);
    }
	else
	{
        printf("\r\nSDRAM test successed!");
        delay_1ms(1000);
        printf("\r\nThe data is:\r\n");
        delay_1ms(1000);
        for(i=0;i < BUFFER_SIZE;i++)
		{
            printf("%6x",rxbuffer[i]);
            if(((i+1)%16) == 0)
			{
                printf("\r\n");
            }
        }
        /* success, light on LED1 */
        gd_eval_led_on(LED1);
    }

    while(1);
}

First, various peripherals and SDRAM are initialized, then specific data is written to SDRAM, the data is read out, and finally the written and read data are compared to see if they are the same.

Here is a look at the specific process of SDRAM initialization:

void exmc_synchronous_dynamic_ram_init(uint32_t sdram_device)
{
    exmc_sdram_parameter_struct        sdram_init_struct;
    exmc_sdram_timing_parameter_struct  sdram_timing_init_struct;
    exmc_sdram_command_parameter_struct     sdram_command_init_struct;

    uint32_t command_content = 0, bank_select;
    uint32_t timeout = SDRAM_TIMEOUT;

    /* enable EXMC clock*/
    rcu_periph_clock_enable(RCU_EXMC);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOD);
    rcu_periph_clock_enable(RCU_GPIOE);
    rcu_periph_clock_enable(RCU_GPIOF);
    rcu_periph_clock_enable(RCU_GPIOG);
    rcu_periph_clock_enable(RCU_GPIOH);

    /* common GPIO configuration */
    /* SDNE0(PC2),SDCKE0(PC5) pin configuration */ 
    gpio_af_set(GPIOC, GPIO_AF_12, GPIO_PIN_2 | GPIO_PIN_5);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2 | GPIO_PIN_5);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2 | GPIO_PIN_5);

    /* D2(PD0),D3(PD1),D13(PD8),D14(PD9),D15(PD10),D0(PD14),D1(PD15) pin configuration */
    gpio_af_set(GPIOD, GPIO_AF_12, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_8 | GPIO_PIN_9 |
                                   GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_8 | GPIO_PIN_9 |
                                                         GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_8 | GPIO_PIN_9 |
                                                                     GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);

    /* NBL0(PE0),NBL1(PE1),D4(PE7),D5(PE8),D6(PE9),D7(PE10),D8(PE11),D9(PE12),D10(PE13),D11(PE14),D12(PE15) pin configuration */
    gpio_af_set(GPIOE, GPIO_AF_12, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_7  | GPIO_PIN_8 |
                                   GPIO_PIN_9  | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
                                   GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_7  | GPIO_PIN_8 |
                                                         GPIO_PIN_9  | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
                                                         GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_7  | GPIO_PIN_8 |
                                                                     GPIO_PIN_9  | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
                                                                     GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

    /* A0(PF0),A1(PF1),A2(PF2),A3(PF3),A4(PF4),A5(PF5),NRAS(PF11),A6(PF12),A7(PF13),A8(PF14),A9(PF15) pin configuration */
    gpio_af_set(GPIOF, GPIO_AF_12, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_2  | GPIO_PIN_3  |
                                   GPIO_PIN_4  | GPIO_PIN_5  | GPIO_PIN_11 | GPIO_PIN_12 |
                                   GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_2  | GPIO_PIN_3  |
                                                         GPIO_PIN_4  | GPIO_PIN_5  | GPIO_PIN_11 | GPIO_PIN_12 |
                                                         GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
    gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_2  | GPIO_PIN_3  |
                                                                     GPIO_PIN_4  | GPIO_PIN_5  | GPIO_PIN_11 | GPIO_PIN_12 |
                                                                     GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);

    /* A10(PG0),A11(PG1),A12(PG2),A14(PG4),A15(PG5),SDCLK(PG8),NCAS(PG15) pin configuration */
    gpio_af_set(GPIOG, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | 
                                   GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
    gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | 
                                                         GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
    gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | 
                                                                     GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15);
    /* SDNWE(PH5) pin configuration */
    gpio_af_set(GPIOH, GPIO_AF_12, GPIO_PIN_5);
    gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_5);
    gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5);

    /* specify which SDRAM to read and write */
    if(EXMC_SDRAM_DEVICE0 == sdram_device)
    {
        bank_select = EXMC_SDRAM_DEVICE0_SELECT;
    }
    else
    {
        bank_select = EXMC_SDRAM_DEVICE1_SELECT;
    }

    /* EXMC SDRAM device initialization sequence --------------------------------*/
	//【1】配置SDRAM时间寄存器
    /* Step 1 : configure SDRAM timing registers --------------------------------*/
    /* LMRD: 2 clock cycles */
    sdram_timing_init_struct.load_mode_register_delay = 2;
    /* XSRD: min = 67ns */
    sdram_timing_init_struct.exit_selfrefresh_delay = 7; 
    /* RASD: min=42ns , max=120k (ns) */
    sdram_timing_init_struct.row_address_select_delay = 5;
    /* ARFD: min=60ns */
    sdram_timing_init_struct.auto_refresh_delay = 6;
    /* WRD:  min=1 Clock cycles +6ns */
    sdram_timing_init_struct.write_recovery_delay = 2;
    /* RPD:  min=18ns */
    sdram_timing_init_struct.row_precharge_delay = 2;
    /* RCD:  min=18ns */
    sdram_timing_init_struct.row_to_column_delay = 2;
    
	//【2】配置SDRAM控制寄存器
    /* step 2 : configure SDRAM control registers ---------------------------------*/
    sdram_init_struct.sdram_device = sdram_device;
    sdram_init_struct.column_address_width = EXMC_SDRAM_COW_ADDRESS_9;
    sdram_init_struct.row_address_width = EXMC_SDRAM_ROW_ADDRESS_13;
    sdram_init_struct.data_width = EXMC_SDRAM_DATABUS_WIDTH_16B;
    sdram_init_struct.internal_bank_number = EXMC_SDRAM_4_INTER_BANK;
    sdram_init_struct.cas_latency = EXMC_CAS_LATENCY_3_SDCLK; 
    sdram_init_struct.write_protection = DISABLE;
    sdram_init_struct.sdclock_config = EXMC_SDCLK_PERIODS_2_HCLK;  
    sdram_init_struct.brust_read_switch = ENABLE;
    sdram_init_struct.pipeline_read_delay = EXMC_PIPELINE_DELAY_1_HCLK;
    sdram_init_struct.timing  = &sdram_timing_init_struct;
    /* EXMC SDRAM bank initialization */
    exmc_sdram_init(&sdram_init_struct);

    //【3】配置CKE?
    /* step 3 : configure CKE high command---------------------------------------*/
    sdram_command_init_struct.command = EXMC_SDRAM_CLOCK_ENABLE;
    sdram_command_init_struct.bank_select = bank_select;
    sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
    sdram_command_init_struct.mode_register_content = 0;
    /* wait until the SDRAM controller is ready */ 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0))
    {
        timeout--;
    }
    /* send the command */
    exmc_sdram_command_config(&sdram_command_init_struct);

	//【4】延时10ms
    /* step 4 : insert 10ms delay----------------------------------------------*/
    delay_1ms(10);

	//【5】配置预充电
    /* step 5 : configure precharge all command----------------------------------*/
    sdram_command_init_struct.command = EXMC_SDRAM_PRECHARGE_ALL;
    sdram_command_init_struct.bank_select = bank_select;
    sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
    sdram_command_init_struct.mode_register_content = 0;
    /* wait until the SDRAM controller is ready */
    timeout = SDRAM_TIMEOUT; 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0))
    {
        timeout--;
    }
    /* send the command */
    exmc_sdram_command_config(&sdram_command_init_struct);

	//【6】配置自动刷新
    /* step 6 : configure Auto-Refresh command-----------------------------------*/
    sdram_command_init_struct.command = EXMC_SDRAM_AUTO_REFRESH;
    sdram_command_init_struct.bank_select = bank_select;
    sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_8_SDCLK;
    sdram_command_init_struct.mode_register_content = 0;
    /* wait until the SDRAM controller is ready */ 
    timeout = SDRAM_TIMEOUT; 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0))
    {
        timeout--;
    }
    /* send the command */
    exmc_sdram_command_config(&sdram_command_init_struct);

	//【7】配置装载模式寄存器
    /* step 7 : configure load mode register command-----------------------------*/
    /* program mode register */
    command_content = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1        |
                                SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
                                SDRAM_MODEREG_CAS_LATENCY_3           |
                                SDRAM_MODEREG_OPERATING_MODE_STANDARD |
                                SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;

    sdram_command_init_struct.command = EXMC_SDRAM_LOAD_MODE_REGISTER;
    sdram_command_init_struct.bank_select = bank_select;
    sdram_command_init_struct.auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK;
    sdram_command_init_struct.mode_register_content = command_content;

    /* wait until the SDRAM controller is ready */ 
    timeout = SDRAM_TIMEOUT; 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0))
    {
        timeout--;
    }
    /* send the command */
    exmc_sdram_command_config(&sdram_command_init_struct);

	//【8】配置自动刷新频率
    /* step 8 : set the auto-refresh rate counter--------------------------------*/
    /* 64ms, 8192-cycle refresh, 64ms/8192=7.81us */
    /* SDCLK_Freq = SYS_Freq/2 */
    /* (7.81 us * SDCLK_Freq) - 20 */
    exmc_sdram_refresh_count_set(761);

    /* wait until the SDRAM controller is ready */ 
    timeout = SDRAM_TIMEOUT; 
    while((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0))
    {
        timeout--;
    }
}

4 Operation Effect

The operation effect is displayed through the serial port and LED, and the read and write operations are compared. If the data is consistent, LED1 is lit, otherwise LED3 is lit. At the same time, the serial port outputs the following information:

SDRAM initialized!
SDRAM write data...
SDRAM read data...
Check the data!
SDRAM test successed!
The data is:
     0     1     2     3     4     5     6     7     8     9     a     b     c     d     e     f
    10    11    12    13    14    15    16    17    18    19    1a    1b    1c    1d    1e    1f
    20    21    22    23    24    25    26    27    28    29    2a    2b    2c    2d    2e    2f
    30    31    32    33    34    35    36    37    38    39    3a    3b    3c    3d    3e    3f
    40    41    42    43    44    45    46    47    48    49    4a    4b    4c    4d    4e    4f
    50    51    52    53    54    55    56    57    58    59    5a    5b    5c    5d    5e    5f
    60    61    62    63    64    65    66    67    68    69    6a    6b    6c    6d    6e    6f
    70    71    72    73    74    75    76    77    78    79    7a    7b    7c    7d    7e    7f
    80    81    82    83    84    85    86    87    88    89    8a    8b    8c    8d    8e    8f
    90    91    92    93    94    95    96    97    98    99    9a    9b    9c    9d    9e    9f
...略

This example program sometimes fails to run. The operation of SDRAM is a bit complicated, I haven't fully understood it yet, I will continue to study it when I have time.

This post is from GD32 MCU

Latest reply

Is SDRAM used to store data? Or what is it used for?   Details Published on 2021-3-23 09:43
 

1w

Posts

204

Resources
2
 

GigaDevice GD32450I-EVAL

Summary post: https://en.eeworld.com/bbs/thread-1140981-1-1.html

This post is from GD32 MCU
Add and join groups EEWorld service account EEWorld subscription account Automotive development circle
 
Personal signature

玩板看这里:

http://en.eeworld.com/bbs/elecplay.html

EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!

 
 

1366

Posts

6

Resources
3
 

Turn down the clock

This post is from GD32 MCU
 
 
 

15

Posts

1

Resources
4
 

Is SDRAM used to store data? Or what is it used for?

This post is from GD32 MCU

Comments

SDRAM is RAM, which is running memory. It can be compared to the memory stick of a computer. It is the memory space used for data calculation when the program is running.  Details Published on 2021-3-27 19:08
 
 
 

291

Posts

5

Resources
5
 
seaguxx posted on 2021-3-23 09:43 Is SDRAM used to store data? Or what is it used for?

SDRAM is RAM, which is running memory. It can be compared to the memory stick of a computer. It is the memory space used for data calculation when the program is running.

This post is from GD32 MCU
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list