TL-LED 发表于 2024-8-2 17:07

【瑞萨RA8D1板卡】 SDRAM读写测试

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>一、SDRAM</strong></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">1.1、SDRAM电路</span></p>

<p><span style="font-size:16px;">开发板上扩展了一片16位总线,32M字节的SDRAM</span></p>

<p><span style="font-size:16px;"></span></p>

<p><span style="font-size:16px;">1.2、SDRAM配置</span></p>

<p><span style="font-size: 16px;">创建的工程中,SDRAM端口已经配置过了。</span></p>

<p><span style="font-size:16px;"></span></p>

<p>&nbsp;</p>

<p><strong><span style="font-size:16px;">二、程序部分</span></strong></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.1、board_sdram.c</span></p>

<pre>
<code>/*
* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
*
* SPDX-License-Identifier: BSD-3-Clause
*/

/***********************************************************************************************************************
* Includes   &lt;System Includes&gt; , "Project Includes"
**********************************************************************************************************************/

#include "r_ioport.h"
#include "bsp_cfg.h"
#include "bsp_pin_cfg.h"

#include "sdram/board_sdram.h"

/***********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/

/* SDRAM size, in bytes */
#define SDRAM_SIZE                           (32 * 1024 * 1024)

/*
* Set ACTIVE-to-PRECHARGE command (tRAS) timing
* e.g. tRAS = 42ns -&gt; 6cycles are needed at SDCLK 120MHz
*      tRAS = 37ns -&gt; 5cycles are needed at SDCLK 120MHz
*/
#define BSP_PRV_SDRAM_TRAS                     (6U)

/*
* Set ACTIVE-to-READ or WRITE delay tRCD (tRCD) timing
* e.g. tRCD = 18ns -&gt; 3cycles are needed at SDCLK 120MHz
*      tRCD = 15ns -&gt; 2cycles are needed at SDCLK 120MHz
*/
#define BSP_PRV_SDRAM_TRCD                     (3U)

/*
* Set PRECHARGE command period (tRP) timing
* e.g. tRP= 18ns -&gt; 3cycles are needed at SDCLK 120MHz
*      tRP= 15ns -&gt; 2cycles are needed at SDCLK 120MHz
*/
#define BSP_PRV_SDRAM_TRP                      (3U)

/*
* Set WRITE recovery time (tWR) timing
* e.g. tWR= 1CLK + 6ns -&gt; 2cycles are needed at SDCLK 120MHz
*      tWR= 1CLK + 7ns -&gt; 2cycles are needed at SDCLK 120MHz
*/
#define BSP_PRV_SDRAM_TWR                      (2U)

/*
* Set CAS (READ) latency (CL) timing
* e.g. CL = 18ns -&gt; 3cycles are needed at SDCLK 120MHz
* e.g. CL = 15ns -&gt; 2cycles are needed at SDCLK 120MHz
*/
#define BSP_PRV_SDRAM_CL                     (3U)

/*
* Set AUTO REFRESH period (tRFC) timing
* e.g. tRFC = 60nS -&gt; 8cycles are needed at SDCLK 120MHz
*      tRFC = 66nS -&gt; 8cycles are needed at SDCLK 120MHz
*/
#define BSP_PRV_SDRAM_TRFC                     (8U)

/*
* Set Average Refresh period
* e.g. tREF = 64ms/8192rows -&gt; 7.8125us/each row.937cycles are needed at SDCLK 120MHz
*/
#define BSP_PRV_SDRAM_REF_CMD_INTERVAL         (937U)

/*
* Set Auto-Refresh issue times in initialization sequence needed for SDRAM device
* Typical SDR SDRAM device needs twice of Auto-Refresh command issue
*/
#define BSP_PRV_SDRAM_SDIR_REF_TIMES         (2U)

/*
* Set RAW address offset
* Available settings are
* 8: 8-bit
* 9: 9-bit
* 10 : 10-bit
* 11 : 11-bit
*/
#define BSP_PRV_SDRAM_SDADR_ROW_ADDR_OFFSET    8//(10U)

/*
* Select endian mode for SDRAM address space
* 0 : Endian of SDRAM address space is the same as the endian of operating mode
* 1 : Endian of SDRAM address space is not the endian of operating mode
*/
#define BSP_PRV_SDRAM_ENDIAN_MODE            (0U)

/*
* Select access mode
* Typically Continuous access should be enabled to get better SDRAM bandwidth
* 0: Continuous access is disabled
* 1: Continuous access is enabled
*/
#define BSP_PRV_SDRAM_CONTINUOUS_ACCESSMODE    (1U)

/*
* Select bus width
* 0: 16-bit
* 1: 32-bit
* 2: 8-bit
*/
#define BSP_PRV_SDRAM_BUS_WIDTH                (0U)

#if ((BSP_PRV_SDRAM_SDADR_ROW_ADDR_OFFSET != 8U) &amp;&amp; (BSP_PRV_SDRAM_SDADR_ROW_ADDR_OFFSET != 9U) \
    &amp;&amp; (BSP_PRV_SDRAM_SDADR_ROW_ADDR_OFFSET != 10U) &amp;&amp; (BSP_PRV_SDRAM_SDADR_ROW_ADDR_OFFSET &gt; 11U))
#error "BSP_PRV_SDRAM_SDADR_ROW_ADDR_OFFSET must be either of 8,9,10 or 11"
#endif

#if ((BSP_PRV_SDRAM_BUS_WIDTH != 0) &amp;&amp; (BSP_PRV_SDRAM_BUS_WIDTH != 1U) &amp;&amp; (BSP_PRV_SDRAM_BUS_WIDTH != 2U))
#error "BSP_PRV_SDRAM_BUS_WIDTH must be either of 0(16-bit) or 1(32-bit) or 2(8-bit)"
#endif

#if ((BSP_PRV_SDRAM_ENDIAN_MODE != 0) &amp;&amp; (BSP_PRV_SDRAM_ENDIAN_MODE != 1))
#error \
    "BSP_PRV_SDRAM_ENDIAN_MODE must be either of 0(same endian as operating mode) or 2(another endian against operating mode)"
#endif

#if ((BSP_PRV_SDRAM_CONTINUOUS_ACCESSMODE != 0) &amp;&amp; (BSP_PRV_SDRAM_CONTINUOUS_ACCESSMODE != 1))
#error \
    "BSP_PRV_SDRAM_CONTINUOUS_ACCESSMODE must be either of 0(continuous access is disabled) or 1(continuous access is enabled)"
#endif

#define BSP_PRV_SDRAM_MR_WB_SINGLE_LOC_ACC    (1U) /* MR.M9                : Single Location Access */
#define BSP_PRV_SDRAM_MR_OP_MODE            (0U) /* MR.M8:M7             : Standard Operation */
#define BSP_PRV_SDRAM_MR_BT_SEQUENCTIAL       (0U) /* MR.M3 Burst Type   : Sequential */
#define BSP_PRV_SDRAM_MR_BURST_LENGTH         (0U) /* MR.M2:M0 Burst Length: 0(1 burst) */

/***********************************************************************************************************************
* Typedef definitions
**********************************************************************************************************************/

/***********************************************************************************************************************
* Exported global variables (to be accessed by other files)
**********************************************************************************************************************/

/***********************************************************************************************************************
* Private global variables and functions
**********************************************************************************************************************/

void bsp_sdram_init (void)
{
    /** Setting for SDRAM initialization sequence */
#if (BSP_PRV_SDRAM_TRP &lt; 3)
    R_BUS-&gt;SDRAM.SDIR_b.PRC = 3U;
#else
    R_BUS-&gt;SDRAM.SDIR_b.PRC = BSP_PRV_SDRAM_TRP - 3U;
#endif

    while (R_BUS-&gt;SDRAM.SDSR)
    {
      /* According to h/w maual, need to confirm that all the status bits in SDSR are 0 before SDIR modification. */
    }

    R_BUS-&gt;SDRAM.SDIR_b.ARFC = BSP_PRV_SDRAM_SDIR_REF_TIMES;

    while (R_BUS-&gt;SDRAM.SDSR)
    {
      /* According to h/w maual, need to confirm that all the status bits in SDSR are 0 before SDIR modification. */
    }

#if (BSP_PRV_SDRAM_TRFC &lt; 3)
    R_BUS-&gt;SDRAM.SDIR_b.ARFI = 0U;
#else
    R_BUS-&gt;SDRAM.SDIR_b.ARFI = BSP_PRV_SDRAM_TRFC - 3U;
#endif

    while (R_BUS-&gt;SDRAM.SDSR)
    {
      /* According to h/w maual, need to confirm that all the status bits in SDSR are 0 before SDICR modification. */
    }

    /** Start SDRAM initialization sequence.
   * Following operation is automatically done when set SDICR.INIRQ bit.
   * Perform a PRECHARGE ALL command and wait at least tRP time.
   * Issue an AUTO REFRESH command and wait at least tRFC time.
   * Issue an AUTO REFRESH command and wait at least tRFC time.
   */
    R_BUS-&gt;SDRAM.SDICR_b.INIRQ = 1U;
    while (R_BUS-&gt;SDRAM.SDSR_b.INIST)
    {
      /* Wait the end of initialization sequence. */
    }

    /** Setting for SDRAM controller */
    R_BUS-&gt;SDRAM.SDCCR_b.BSIZE= BSP_PRV_SDRAM_BUS_WIDTH;             /* set SDRAM bus width */
    R_BUS-&gt;SDRAM.SDAMOD_b.BE    = BSP_PRV_SDRAM_CONTINUOUS_ACCESSMODE; /* enable continuous access */
    R_BUS-&gt;SDRAM.SDCMOD_b.EMODE = BSP_PRV_SDRAM_ENDIAN_MODE;         /* set endian mode for SDRAM address space */

    while (R_BUS-&gt;SDRAM.SDSR)
    {
      /* According to h/w maual, need to confirm that all the status bits in SDSR are 0 before SDMOD modification. */
    }

    /** Using LMR command, program the mode register */
    R_BUS-&gt;SDRAM.SDMOD = ((((uint16_t) (BSP_PRV_SDRAM_MR_WB_SINGLE_LOC_ACC &lt;&lt; 9) |
                            (uint16_t) (BSP_PRV_SDRAM_MR_OP_MODE &lt;&lt; 7)) |
                           (uint16_t) (BSP_PRV_SDRAM_CL &lt;&lt; 4)) |
                        (uint16_t) (BSP_PRV_SDRAM_MR_BT_SEQUENCTIAL &lt;&lt; 3)) |
                         (uint16_t) (BSP_PRV_SDRAM_MR_BURST_LENGTH &lt;&lt; 0);

    /** wait at least tMRD time */
    while (R_BUS-&gt;SDRAM.SDSR_b.MRSST)
    {
      /* Wait until Mode Register setting done. */
    }

    /** Set timing parameters for SDRAM */
    R_BUS-&gt;SDRAM.SDTR_b.RAS = BSP_PRV_SDRAM_TRAS - 1U; /* set ACTIVE-to-PRECHARGE command cycles*/
    R_BUS-&gt;SDRAM.SDTR_b.RCD = BSP_PRV_SDRAM_TRCD - 1U; /* set ACTIVE to READ/WRITE delay cycles */
    R_BUS-&gt;SDRAM.SDTR_b.RP= BSP_PRV_SDRAM_TRP - 1U;/* set PRECHARGE command period cycles */
    R_BUS-&gt;SDRAM.SDTR_b.WR= BSP_PRV_SDRAM_TWR - 1U;/* set write recovery cycles */
    R_BUS-&gt;SDRAM.SDTR_b.CL= BSP_PRV_SDRAM_CL;      /* set SDRAM column latency cycles */

    /** Set row address offset for target SDRAM */
    R_BUS-&gt;SDRAM.SDADR_b.MXC = BSP_PRV_SDRAM_SDADR_ROW_ADDR_OFFSET - 8U;

    R_BUS-&gt;SDRAM.SDRFCR_b.REFW = (uint16_t) (BSP_PRV_SDRAM_TRFC - 1U); /* set Auto-Refresh issuing cycle */
    R_BUS-&gt;SDRAM.SDRFCR_b.RFC= BSP_PRV_SDRAM_REF_CMD_INTERVAL - 1U;/* set Auto-Refresh period */

    /** Start Auto-refresh */
    R_BUS-&gt;SDRAM.SDRFEN_b.RFEN = 1U;

    /** Enable SDRAM access */
    R_BUS-&gt;SDRAM.SDCCR_b.EXENB = 1U;
}
</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.2、board_sdram.h</span></p>

<pre>
<code>/*
* Copyright (c) 2020 - 2024 Renesas Electronics Corporation and/or its affiliates
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef BOARD_SDRAM_H
#define BOARD_SDRAM_H

/***********************************************************************************************************************
* Includes   &lt;System Includes&gt; , "Project Includes"
**********************************************************************************************************************/

/***********************************************************************************************************************
* Macro definitions
**********************************************************************************************************************/

/***********************************************************************************************************************
* Typedef definitions
**********************************************************************************************************************/

/***********************************************************************************************************************
* Exported global variables (to be accessed by other files)
**********************************************************************************************************************/

void bsp_sdram_init(void);

/***********************************************************************************************************************
* Private global variables and functions
**********************************************************************************************************************/

#endif
</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.3、sdram_test.c</span></p>

<pre>
<code>/*
* sdram_test.c
*/
#include "hal_data.h"
#include "sdram/board_sdram.h"
#include &lt;stdio.h&gt;

#define DCACHE_Enable   0
#define DTCM_Used       1


//extern void mpu_direct_config(void);
void DWT_init();
uint32_t DWT_get_count();
void DWT_clean_count();
uint32_t DWT_count_to_us(uint32_t delta_count);

#define DWT_DEM *(uint32_t*)0xE000EDFC

void DWT_init()
{
    DWT-&gt;CTRL = 0;
    DWT_DEM |= 1&lt;&lt;24;
    DWT-&gt;CYCCNT = 0;
    DWT-&gt;CTRL |= 1&lt;&lt;0;
}


uint32_t DWT_get_count()
{
    return DWT-&gt;CYCCNT;
}

void DWT_clean_count()
{
    DWT-&gt;CYCCNT = 0;
}

uint32_t DWT_count_to_us(uint32_t delta_count)
{
    return delta_count/480;
}


uint32_t DWT_pre_count=0, DWT_post_count=0, time_sdram_access=0;
uint32_t DWT_delta=0;

#define SEMC_EXAMPLE_DATALEN    256//4096
#define SEMC_EXAMPLE_WRITETIMES (1000U)

uint32_t write_buff;// BSP_ALIGN_VARIABLE(64) BSP_PLACE_IN_SECTION(".itcm_data");
uint32_t read_buff;
uint32_t dtcm_read_buff BSP_PLACE_IN_SECTION(".dtcm_data");


void SDRAMReadWrite32Bit(void) ;

#define EXAMPLE_SDRAM_START_ADDRESS (0x68000000U)
#define EXAMPLE_DTCM_START_ADDRESS(0x20000000U)


void SDRAMReadWrite32Bit(void)
{
    uint32_t index;
    uint32_t datalen = SEMC_EXAMPLE_DATALEN ;
    uint32_t *sdram= (uint32_t *)EXAMPLE_SDRAM_START_ADDRESS; /* SDRAM start address. */
    uint32_t *dtcm_buffer= (uint32_t *)EXAMPLE_DTCM_START_ADDRESS;

    memset((uint32_t *)dtcm_buffer, 0 ,datalen);
    memset((uint32_t *)write_buff, 0 ,datalen);
    memset((uint32_t *)sdram, 0 ,datalen);
    for(uint16_t i=0; i&lt;datalen; i++)
    {
       write_buff = i;
    }
    for (index = 0; index &lt; datalen; index++)
    {
#if DTCM_Used
    dtcm_buffer= write_buff;//index;
#else

#endif
    }
#if DCACHE_Enable
    SCB_EnableDCache();
#endif
   DWT_init();
   DWT_clean_count();
   DWT_pre_count = DWT_get_count();

   for (index = 0; index &lt; datalen; index++)
   {
#if DTCM_Used
    sdram= dtcm_buffer;//source 为 DTCM
#else
    sdram= write_buff;//source 为 SRAM
#endif
   }
   DWT_post_count = DWT_get_count();
   DWT_delta = DWT_post_count - DWT_pre_count;
   if(DWT_delta==0)
   {
       printf("DWT count error! \r\n");
   }
   time_sdram_access = DWT_count_to_us(DWT_delta);
#if DCACHE_Enable
    SCB_DisableDCache();
#endif

   if(time_sdram_access==0)
   {
       while(1){;}
   }
   printf("SDRAM write %d bytes data finished! \r\n" , SEMC_EXAMPLE_DATALEN);

   R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);

       /* Read data from the SDRAM. */
#if DCACHE_Enable
       SCB_EnableDCache();
#endif
   memset((uint32_t *)dtcm_buffer, 0 ,datalen);
   time_sdram_access = 0;
   DWT_init();
   DWT_clean_count();
   DWT_pre_count = DWT_get_count();

   for (index = 0; index &lt; datalen; index++)
   {
#if DTCM_Used
    dtcm_read_buff = sdram;
#else
    read_buff = sdram;
#endif
    }
   DWT_post_count = DWT_get_count();
   DWT_delta = DWT_post_count - DWT_pre_count;
   while(DWT_delta==0)
   {
   }
   time_sdram_access = DWT_count_to_us(DWT_delta);
   if(time_sdram_access==0)
   {
       while(1){;}
   }

#if DCACHE_Enable
    SCB_DisableDCache();
#endif
       printf("SDRAM read %d bytes data finished! \r\n" , SEMC_EXAMPLE_DATALEN);
       printf("SDRAM read back data: \r\n");
       /* Compare the two buffers. */
       while (datalen--)
       {
         printf("0x%3x", sdram);
         if(datalen%16==0)
         {
               printf("\r\n");
         }
#if DTCM_Used
      if (dtcm_buffer != sdram)
      {
            printf("SDRAM test error! \r\n");
            while(1){;}
      }
#else
      if (read_buff != sdram)
      {
            printf("SDRAM test error! \r\n");
            while(1){;}
      }
#endif
       }

       printf("SDRAM test pass! \r\n");

}

</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.4、hal_entry.c</span></p>

<pre>
<code>#include "hal_data.h"
#include "led/led.h"
#include "debug_uart/bsp_debug_uart.h"
#include "sdram/board_sdram.h"
#include "sdram/sdram_test.h"

fsp_err_t err;

void R_BSP_WarmStart(bsp_warm_start_event_t event);

/*******************************************************************************************************************//**
* @brief Blinky example application
*
* Blinks all leds at a rate of 1 second using the software delay function provided by the BSP.
*
**********************************************************************************************************************/
void hal_entry (void)
{
    init_led();
    Debug_UART3_Init();
    bsp_sdram_init();
    printf("SDRAM read/write test start!\r\n");
    SDRAMReadWrite32Bit();
    while (1)
    {
      /* Delay */
      //R_BSP_SoftwareDelay(delay, bsp_delay_units);
      R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
      led201_on();
      R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
      led201_off();
    }
}</code></pre>

<p>&nbsp;</p>

<p><strong><span style="font-size:16px;">三、测试结果</span></strong></p>

<p>&nbsp;</p>

<p></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p><strong><span style="font-size:16px;">四、附件</span></strong></p>

<p><span style="font-size:16px;">源代码:</span></p>

<div></div>

Jacktang 发表于 2024-8-4 09:08

<p>代码好长</p>

<p>测试结果是正确的吧</p>

TL-LED 发表于 2024-8-4 22:11

Jacktang 发表于 2024-8-4 09:08
代码好长

测试结果是正确的吧

<p>测试正常的,使用官网的测试例程。</p>
页: [1]
查看完整版本: 【瑞萨RA8D1板卡】 SDRAM读写测试