# GD32 EXMC SDRAM 在 Zephyr RTOS 上的移植与实践
## 摘要
本文详细介绍了将GD32F527微控制器的EXMC SDRAM控制器驱动移植到Zephyr RTOS的过程。通过利用Zephyr的MEMC子系统,我们实现了SDRAM的自动初始化,用户只需在配置文件中启用两个选项即可直接使用外部SDRAM,大大简化了开发流程。
一、引言GD32F527是兆易创新推出的高性能ARM Cortex-M33内核MCU,主频达200MHz,内置强大的外部存储控制器(EXMC),支持SDRAM、NAND Flash等外部存储器的扩展。在嵌入式图形显示应用中,SDRAM作为LCD帧缓冲区可以支持更高分辨率的显示。Zephyr RTOS是一款面向物联网的实时操作系统,提供了丰富的驱动框架和设备模型。其MEMC子系统为外部存储控制器提供了统一的接口支持。本文的目标是将GD32的EXMC SDRAM驱动集成到Zephyr的MEMC子系统中,实现一键配置SDRAM。 二、硬件平台与开发环境2.1 硬件平台MCU: GD32F527VCT6 (ARM Cortex-M33, 200MHz)开发板: GD32F527I-EVALSDRAM: IS42S16400J (8MB, 16位数据宽度)LCD: 480x272 RGB TFT显示屏
2.2 软件环境
-RTOS: Zephyr Project v4.3.0编译工具: ARM GCC调试工具: J-Link + Ozone
2.3 SDRAM硬件连接
三、Zephyr MEMC子系统概述
Zephyr的MEMC(Memory Controller)子系统为外部存储控制器提供了标准化的设备模型。开发者只需:
1. 在设备树中配置SDRAM参数2. 在Kconfig中启用MEMC驱动3. 在代码中直接使用SDRAM地址
系统启动时会自动初始化SDRAM,无需手动编写初始化代码。
四、移植过程
4.1 设备树配置
首先需要在设备树中添加SDRAM节点配置:
4.2 设备树绑定
创建设备树绑定文件 `dts/bindings/memc/gd,gd32-exmc-sdram.yaml`:
驱动核心代码位于 `drivers/memc/memc_gd32_sdram.c`:
在驱动Kconfig中添加配置选项:
4.5 用户配置
用户只需在项目的 `prj.conf` 中添加:
五、关键注意事项
5.1 HAL库位域配置
直接使用数值会导致位字段错位,SDRAM无法正常工作。
5.2 SystemCoreClock配置
EXMC初始化需要正确的SystemCoreClock值用于时序计算。在驱动初始化时需要强制设置为200MHz:
访问外部SDRAM时需要禁用MPU和Data Cache:
6.1 SDRAM测试
配置LCD使用SDRAM作为帧缓冲区:
七、测试结果
通过MEMC驱动的自动初始化,SDRAM测试全部通过:
八、总结
本文详细介绍了GD32 EXMC SDRAM在Zephyr RTOS上的移植过程。通过以下改进实现了"一键配置":
集成到MEMC子系统:利用Zephyr的设备模型,实现自动初始化使用GD32固件库:直接调用HAL函数,确保兼容性完善位域配置:全部使用官方宏定义,避免配置错误
用户现在只需在配置文件中启用两个选项即可使用SDRAM,无需编写任何初始化代码:
参考资料
1. Zephyr Project Documentation - MEMC Subsystem2. GD32F5xx Firmware Library3. GD32F527 User Manual4. IS42S16400J SDRAM Datasheet
## 摘要
本文详细介绍了将GD32F527微控制器的EXMC SDRAM控制器驱动移植到Zephyr RTOS的过程。通过利用Zephyr的MEMC子系统,我们实现了SDRAM的自动初始化,用户只需在配置文件中启用两个选项即可直接使用外部SDRAM,大大简化了开发流程。
一、引言GD32F527是兆易创新推出的高性能ARM Cortex-M33内核MCU,主频达200MHz,内置强大的外部存储控制器(EXMC),支持SDRAM、NAND Flash等外部存储器的扩展。在嵌入式图形显示应用中,SDRAM作为LCD帧缓冲区可以支持更高分辨率的显示。Zephyr RTOS是一款面向物联网的实时操作系统,提供了丰富的驱动框架和设备模型。其MEMC子系统为外部存储控制器提供了统一的接口支持。本文的目标是将GD32的EXMC SDRAM驱动集成到Zephyr的MEMC子系统中,实现一键配置SDRAM。 二、硬件平台与开发环境2.1 硬件平台MCU: GD32F527VCT6 (ARM Cortex-M33, 200MHz)开发板: GD32F527I-EVALSDRAM: IS42S16400J (8MB, 16位数据宽度)LCD: 480x272 RGB TFT显示屏
2.2 软件环境
-RTOS: Zephyr Project v4.3.0编译工具: ARM GCC调试工具: J-Link + Ozone
2.3 SDRAM硬件连接
SDRAM连接到EXMC Bank0,基地址为0xC0000000:

三、Zephyr MEMC子系统概述
Zephyr的MEMC(Memory Controller)子系统为外部存储控制器提供了标准化的设备模型。开发者只需:
1. 在设备树中配置SDRAM参数2. 在Kconfig中启用MEMC驱动3. 在代码中直接使用SDRAM地址
系统启动时会自动初始化SDRAM,无需手动编写初始化代码。
四、移植过程
4.1 设备树配置
首先需要在设备树中添加SDRAM节点配置:
&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>;
};
};4.2 设备树绑定
创建设备树绑定文件 `dts/bindings/memc/gd,gd32-exmc-sdram.yaml`:
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驱动实现
驱动核心代码位于 `drivers/memc/memc_gd32_sdram.c`:
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配置在驱动Kconfig中添加配置选项:
config MEMC_GD32_EXMC bool "GD32 EXMC SDRAM support" depends on MEMC && GPIO help Enable support for GD32 EXMC SDRAM controller
4.5 用户配置
用户只需在项目的 `prj.conf` 中添加:
# 启用MEMC子系统 CONFIG_MEMC=y # 启用GD32 EXMC SDRAM驱动 CONFIG_MEMC_GD32_EXMC=y
五、关键注意事项
5.1 HAL库位域配置
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 |
5.2 SystemCoreClock配置
EXMC初始化需要正确的SystemCoreClock值用于时序计算。在驱动初始化时需要强制设置为200MHz:
extern uint32_t SystemCoreClock; SystemCoreClock = 200000000;5.3 MPU和Cache配置
访问外部SDRAM时需要禁用MPU和Data Cache:
CONFIG_MPU=n CONFIG_DCACHE=n六、使用示例
6.1 SDRAM测试
#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使用SDRAM作为帧缓冲区:
// 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;
}
}七、测试结果
通过MEMC驱动的自动初始化,SDRAM测试全部通过:
*** 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分辨率的全屏图像。
八、总结
本文详细介绍了GD32 EXMC SDRAM在Zephyr RTOS上的移植过程。通过以下改进实现了"一键配置":
集成到MEMC子系统:利用Zephyr的设备模型,实现自动初始化使用GD32固件库:直接调用HAL函数,确保兼容性完善位域配置:全部使用官方宏定义,避免配置错误
用户现在只需在配置文件中启用两个选项即可使用SDRAM,无需编写任何初始化代码:
CONFIG_MEMC=y CONFIG_MEMC_GD32_EXMC=y这种方法具有良好的可移植性,可以方便地推广到其他GD32F5系列MCU。
参考资料
1. Zephyr Project Documentation - MEMC Subsystem2. GD32F5xx Firmware Library3. GD32F527 User Manual4. IS42S16400J SDRAM Datasheet
实现效果:

我要赚赏金
