SDRAM连接到EXMC Bank0,基地址为0xC0000000:

&exmc {
status = "okay";
gd_sdram: sdram {
compatible = "gd,gd32-exmc-sdram";
status = "okay";
gd_sdram_device = <0>;
gd_sdram_column_bits = <9>;
gd_sdram_row_bits = <13>;
gd_sdram_data_width = <16>;
gd_sdram_bank_count = <4>;
gd_sdram_cas_latency = <3>;
gd_sdram_sdclock = <2>;
gd_sdram_tmr_rcd = <2>;
gd_sdram_tmr_rp = <2>;
gd_sdram_tmr_ras = <6>;
gd_sdram_tmr_rc = <5>;
gd_sdram_tmr_rd = <2>;
gd_sdram_tmr_xsr = <7>;
gd_sdram_tmr_wp = <2>;
gd_sdram_refresh_rate = <761>;
gd_sdram_mode_reg = <0x230>;
};
};description: GD32 EXMC SDRAM Controller compatible: "gd,gd32-exmc-sdram" include: base.yaml properties: gd_sdram_device: type: int required: true gd_sdram_column_bits: type: int required: true gd_sdram_row_bits: type: int required: true gd_sdram_data_width: type: int required: true # ... 其他参数4.3 MEMC驱动实现
static int memc_gd32_sdram_init(const struct device *dev)
{
// 设置SystemCoreClock用于延时计算
SystemCoreClock = 200000000;
// 启用EXMC和GPIO时钟
rcu_periph_clock_enable(RCU_EXMC);
rcu_periph_clock_enable(RCU_GPIOC);
// ... 其他GPIO时钟
// 配置SDRAM引脚
gpio_af_set(GPIOC, GPIO_AF_12, GPIO_PIN_2 | GPIO_PIN_5);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, ...);
// ... 其他引脚配置
// 配置SDRAM时序
timing.row_to_column_delay = config->timing_rcd;
timing.row_precharge_delay = config->timing_rp;
timing.write_recovery_delay = config->timing_trd;
timing.auto_refresh_delay = config->timing_ras;
timing.row_address_select_delay = config->timing_rc;
timing.exit_selfrefresh_delay = config->timing_xsr;
timing.load_mode_register_delay = config->timing_tmr;
// 配置SDRAM控制参数
sdram_config.sdram_device = EXMC_SDRAM_DEVICE0;
sdram_config.pipeline_read_delay = EXMC_PIPELINE_DELAY_1_HCLK;
sdram_config.burst_read_switch = ENABLE;
sdram_config.sdclock_config = EXMC_SDCLK_PERIODS_2_HCLK;
sdram_config.cas_latency = EXMC_CAS_LATENCY_3_SDCLK;
// ...
// 初始化SDRAM
exmc_sdram_init(&sdram_config);
// 发送初始化序列命令
cmd.command = EXMC_SDRAM_CLOCK_ENABLE;
exmc_sdram_command_config(&cmd);
cmd.command = EXMC_SDRAM_PRECHARGE_ALL;
exmc_sdram_command_config(&cmd);
cmd.command = EXMC_SDRAM_AUTO_REFRESH;
cmd.auto_refresh_number = 8;
exmc_sdram_command_config(&cmd);
cmd.command = EXMC_SDRAM_LOAD_MODE_REGISTER;
cmd.mode_register_content = config->mode_reg;
exmc_sdram_command_config(&cmd);
// 设置刷新率
exmc_sdram_refresh_count_set(config->refresh_rate);
return 0;
}4.4 Kconfig配置config MEMC_GD32_EXMC bool "GD32 EXMC SDRAM support" depends on MEMC && GPIO help Enable support for GD32 EXMC SDRAM controller
# 启用MEMC子系统 CONFIG_MEMC=y # 启用GD32 EXMC SDRAM驱动 CONFIG_MEMC_GD32_EXMC=y
GD32 HAL库的EXMC SDRAM配置使用位域结构,必须使用官方定义的宏,不能使用原始数值:
| 参数 | 错误写法 | 正确写法 |
| sdclock_config | 2 | EXMC_SDCLK_PERIODS_2_HCLK |
| sdram_device | 4 | EXMC_SDRAM_DEVICE0 |
| column_address_width | 9 | EXMC_SDRAM_COW_ADDRESS_9 |
| row_address_width | 13 | EXMC_SDRAM_ROW_ADDRESS_13 |
| data_width | 1 | EXMC_SDRAM_DATABUS_WIDTH_16B |
| cas_latency | 3 | EXMC_CAS_LATENCY_3_SDCLK |
| bank_select | 0 | EXMC_SDRAM_DEVICE0_SELECT |
extern uint32_t SystemCoreClock; SystemCoreClock = 200000000;5.3 MPU和Cache配置
CONFIG_MPU=n CONFIG_DCACHE=n六、使用示例
#include <zephyr/kernel.h>
#define SDRAM_BASE 0xC0000000U
int main(void)
{
volatile uint16_t *sdram = (volatile uint16_t *)SDRAM_BASE;
// 写入测试
sdram[0] = 0x55AA;
// 读取验证
if (sdram[0] == 0x55AA) {
printk("SDRAM test PASSED!\n");
} else {
printk("SDRAM test FAILED!\n");
}
return 0;
}6.2 LCD帧缓冲应用// LCD帧缓冲地址
#define FRAMEBUFFER_ADDR 0xC0000000U
// 填充屏幕
void fill_screen(uint16_t color)
{
volatile uint16_t *fb = (volatile uint16_t *)FRAMEBUFFER_ADDR;
for (int i = 0; i < 480 * 272; i++) {
fb[i] = color;
}
}*** Booting Zephyr OS build v4.3.0-6235-g8a139a091dd0 *** [memc_gd32_sdram] GD32 EXMC SDRAM initialized at 0xC0000000 - TEST OK --- Test 1: Basic 16-bit write/read --- PASS: 0x55AA written and read back --- Test 2: Multiple address test --- PASS: All 10 addresses OK --- Test 3: 32-bit write/read --- PASS: 0xDEADBEEF written and read back --- Test 4: Fill patterns --- PASS --- Test 5: March test --- PASS RESULT: SDRAM TEST PASSED!LCD显示也正常工作,可以显示480x272分辨率的全屏图像。
CONFIG_MEMC=y CONFIG_MEMC_GD32_EXMC=y这种方法具有良好的可移植性,可以方便地推广到其他GD32F5系列MCU。
实现效果:
