SDRAM Driver Example Guide
English | 中文
Introduction
This project provides a complete SDRAM driver solution for the Titan Board Mini platform, based on the Renesas RA8P1 microcontroller and RT-Thread real-time operating system. This driver fully utilizes RA8P1’s external memory interface to provide high-performance external memory access for embedded systems.
Key Features
Large capacity: Supports 64MB SDRAM external storage
High-performance access: 32-bit data bus, high-frequency operation capability
Real-time system support: Fully compatible with RT-Thread memory management framework
Complete functionality: Supports initialization, testing, performance evaluation and more
Easy to use: Provides command-line interface for development and debugging
Technical Architecture
User Application Layer
↓
RT-Thread Memory Management Layer
↓
BSP SDRAM Driver Layer
↓
RA8P1 SDRAMC Hardware Controller
↓
Physical SDRAM Chip
Hardware Introduction
2.1 RA8P1 External Memory Interface Features
The RA8P1 microcontroller integrates a powerful external memory interface specifically designed for connecting SDRAM chips. Main features include:
Controller Features
SDRAM Controller (SDRAMC): Dedicated hardware controller for SDRAM timing management
Address/Data multiplexing: Supports time-division multiplexing of address and data lines
32-bit data bus: High-throughput data transmission
Auto-refresh: Built-in auto-refresh mechanism ensuring data integrity
Low-power mode: Supports self-refresh mode for power reduction
Timing Control
Programmable timing: Supports multiple CAS latency settings (CL2, CL3, CL4)
Flexible row/column access: Configurable row precharge and row activation times
Refresh cycle: Programmable auto-refresh interval
Burst length: Supports 1, 2, 4, 8-bit burst transfers
Memory Mapping
#define SDRAM_BASE_ADDR (0x68000000UL) // SDRAM base address
#define SDRAM_SIZE (64 * 1024 * 1024UL) // 64MB size
// Access range: 0x68000000 - 0x68FFFFFF
2.2 Supported SDRAM Types
Current system supported SDRAM configuration:
Chip Specifications
Capacity: 64MB (256Mbit)
Data width: 32-bit
Organization: 4banks × 4M × 32bit
Operating voltage: 3.3V
Access time: Standard synchronous SDRAM
Timing Parameters
// Key timing parameters
#define BSP_CFG_SDRAM_TRAS (6) // Row active to precharge time
#define BSP_CFG_SDRAM_TRCD (3) // Row active to column access time
#define BSP_CFG_SDRAM_TRP (3) // Precharge time
#define BSP_CFG_SDRAM_TWR (2) // Write recovery time
#define BSP_CFG_SDRAM_TCL (3) // CAS latency
#define BSP_CFG_SDRAM_TRFC (937) // Refresh cycle
#define BSP_CFG_SDRAM_TREFW (8) // Refresh wait time
2.3 Hardware Connection
SDRAM chip connects to RA8P1 via the following signal lines:
Data Bus
DQ[31:0]: 32-bit bidirectional data busDQM[3:0]: Data mask signals
Address Bus
A[12:0]: Address lines (multiplexed)BA[1:0]: Bank address select
Control Signals
RAS#: Row address strobeCAS#: Column address strobeWE#: Write enableCS#: Chip selectCKE: Clock enableCLK: Clock signal
Power and Ground
VDD/VSS: Power and groundVDDQ/VSSQ: Data power and ground
Software Architecture
3.1 SDRAM Driver Initialization Flow
SDRAM initialization follows the standard JEDEC specification with the following main steps:
Initialization Sequence
void R_BSP_SdramInit(bool init_memory)
{
// 1. Check status register
while (R_BUS->SDRAM.SDSR) {
// Wait for status register to clear
}
// 2. Set initialization parameters
R_BUS->SDRAM.SDIR = ((BSP_CFG_SDRAM_INIT_ARFI - 3U) << R_BUS_SDRAM_SDIR_ARFI_Pos) |
(BSP_CFG_SDRAM_INIT_ARFC << R_BUS_SDRAM_SDIR_ARFC_Pos) |
((BSP_CFG_SDRAM_INIT_PRC - 3U) << R_BUS_SDRAM_SDIR_PRC_Pos);
// 3. Set bus width
R_BUS->SDRAM.SDCCR = (BSP_CFG_SDRAM_BUS_WIDTH << R_BUS_SDRAM_SDCCR_BSIZE_Pos);
// 4. Enable clock output
R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_CGC);
R_SYSTEM->SDCKOCR = 1;
R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_CGC);
// 5. Execute initialization sequence
R_BUS->SDRAM.SDICR = 1U;
while (R_BUS->SDRAM.SDSR_b.INIST) {
// Wait for initialization to complete
}
// 6. Set access mode
R_BUS->SDRAM.SDAMOD = BSP_CFG_SDRAM_ACCESS_MODE;
R_BUS->SDRAM.SDCMOD = BSP_CFG_SDRAM_ENDIAN_MODE;
// 7. Configure mode register
R_BUS->SDRAM.SDMOD = (BSP_PRV_SDRAM_MR_WB_SINGLE_LOC_ACC << 9) |
(BSP_PRV_SDRAM_MR_OP_MODE << 7) |
(BSP_CFG_SDRAM_TCL << 4) |
(BSP_PRV_SDRAM_MR_BT_SEQUENTIAL << 3) |
(BSP_PRV_SDRAM_MR_BURST_LENGTH << 0);
// 8. Set timing parameters
R_BUS->SDRAM.SDTR = ((BSP_CFG_SDRAM_TRAS - 1U) << R_BUS_SDRAM_SDTR_RAS_Pos) |
((BSP_CFG_SDRAM_TRCD - 1U) << R_BUS_SDRAM_SDTR_RCD_Pos) |
((BSP_CFG_SDRAM_TRP - 1U) << R_BUS_SDRAM_SDTR_RP_Pos) |
((BSP_CFG_SDRAM_TWR - 1U) << R_BUS_SDRAM_SDTR_WR_Pos) |
(BSP_CFG_SDRAM_TCL << R_BUS_SDRAM_SDTR_CL_Pos);
// 9. Set address offset
R_BUS->SDRAM.SDADR = BSP_CFG_SDRAM_MULTIPLEX_ADDR_SHIFT;
// 10. Configure auto-refresh
R_BUS->SDRAM.SDRFCR = ((BSP_CFG_SDRAM_TREFW - 1U) << R_BUS_SDRAM_SDRFCR_REFW_Pos) |
((BSP_CFG_SDRAM_TRFC - 1U) << R_BUS_SDRAM_SDRFCR_RFC_Pos);
// 11. Enable auto-refresh
R_BUS->SDRAM.SDRFEN = 1U;
// 12. Enable SDRAM access
R_BUS->SDRAM.SDCCR = R_BUS_SDRAM_SDCCR_EXENB_Msk |
(BSP_CFG_SDRAM_BUS_WIDTH << R_BUS_SDRAM_SDCCR_BSIZE_POS);
}
Key Step Descriptions
Status check: Ensure SDRAM is in ready state
Initialization parameters: Configure basic parameters like row refresh and precharge
Clock configuration: Enable SDRAM clock signal
Initialization execution: Execute standard SDRAM initialization sequence
Access mode: Set sequential access mode and endianness
Mode register: Configure CAS latency, burst length and other parameters
Timing configuration: Set all critical timing parameters
Address configuration: Configure address multiplexing mode
Refresh configuration: Set auto-refresh parameters
Enable refresh: Start auto-refresh operation
Enable access: Allow CPU to access SDRAM
3.2 Memory Management Mechanism
Memory Allocation Strategy
Contiguous memory pool: Uses fixed-size memory blocks
Alignment requirements: 32-bit data bus requires 4-byte alignment
Cache optimization: Supports DMA direct access
RT-Thread Integration
By default, RT-Thread’s heap is located in on-chip SRAM and cannot directly rt_malloc() large blocks like 64MB. The recommended approach is to create an independent memheap in the SDRAM region or use static buffers with BSP_PLACE_IN_SECTION(".sdram") attribute. The following example demonstrates how to create a memheap named sdram:
#define SDRAM_POOL_SIZE (4 * 1024 * 1024) // Adjust as needed
static uint8_t sdram_pool[SDRAM_POOL_SIZE] BSP_PLACE_IN_SECTION(".sdram");
static struct rt_memheap sdram_heap;
void sdram_heap_init(void)
{
rt_memheap_init(&sdram_heap, "sdram", sdram_pool, sizeof(sdram_pool));
}
void example_use(void)
{
void *sdram_buffer = rt_memheap_alloc(&sdram_heap, 512 * 1024);
if (sdram_buffer)
{
rt_memcpy(sdram_buffer, src_data, 512 * 1024);
rt_memheap_free(sdram_buffer);
}
}
Data Integrity Protection
Initialization verification: Basic testing before each use
Runtime monitoring: Memory access error detection support
Error recovery: Provides error handling mechanism
3.3 BSP Layer Abstraction
BSP Interface Functions
// SDRAM initialization
R_BSP_SdramInit(true);
// Self-refresh mode switching
R_BSP_SdramSelfRefreshEnable(); // Enter self-refresh
R_BSP_SdramSelfRefreshDisable(); // Exit self-refresh
Hardware Abstraction Layer
Register mapping: Unified register access interface
Timing configuration: Configurable timing parameters
Status monitoring: Real-time status query functionality
Usage Examples
4.1 Basic Read/Write Operations
Memory-mapped Access
// SDRAM basic access example
void basic_sdram_access(void)
{
uint32_t *sdram_ptr = (uint32_t *)SDRAM_BASE_ADDR;
uint32_t i;
// Write test data
for (i = 0; i < 1024; i++) {
sdram_ptr[i] = 0xA5A5A5A5 + i;
}
// Read and verify
for (i = 0; i < 1024; i++) {
uint32_t read_data = sdram_ptr[i];
uint32_t expected = 0xA5A5A5A5 + i;
if (read_data != expected) {
rt_kprintf("Error at offset %d: expected 0x%08X, got 0x%08X\n",
i, expected, read_data);
}
}
rt_kprintf("Basic SDRAM access test completed.\n");
}
Bulk Data Operations
// Large data block operation example
void sdram_bulk_operation(void)
{
uint32_t *sdram_ptr = (uint32_t *)SDRAM_BASE_ADDR;
uint32_t *local_buffer = rt_malloc(1024 * 1024); // 1MB
if (!local_buffer) {
rt_kprintf("Failed to allocate local buffer.\n");
return;
}
// Fill local buffer
for (uint32_t i = 0; i < 256 * 1024; i++) {
local_buffer[i] = 0x12345678 + i;
}
// Bulk write to SDRAM
rt_memcpy(sdram_ptr, local_buffer, 1024 * 1024);
// Bulk read for verification
rt_memcpy(local_buffer, sdram_ptr, 1024 * 1024);
// Verify data integrity
uint32_t errors = 0;
for (uint32_t i = 0; i < 256 * 1024; i++) {
if (local_buffer[i] != 0x12345678 + i) {
errors++;
}
}
rt_kprintf("Bulk operation test: %d errors found.\n", errors);
rt_free(local_buffer);
}
Run Effect
Compile and flash the program to the development board, then run sdram_speed_test in the terminal to see the results.
