diff --git a/app/main.cpp b/app/main.cpp index 1fc2158..f36e66c 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -12,62 +12,27 @@ __attribute__((section(".sdram"))) uint8_t sdram_big_buffer[1024 * 1024]; -#define LED1_PORT GPIOE -#define LED1_PIN GPIO_PIN_3 -#define LED2_PORT GPIOD -#define LED2_PIN GPIO_PIN_7 -#define LED3_PORT GPIOG -#define LED3_PIN GPIO_PIN_3 -#define LED4_PORT GPIOA -#define LED4_PIN GPIO_PIN_5 - static void delay_16m(uint32_t ms) { - for (volatile uint32_t i = 0; i < ms * 4000U; i++); -} - -static void led_on(uint32_t port, uint32_t pin) -{ - gpio_bit_set(port, pin); -} - -static void led_off(uint32_t port, uint32_t pin) -{ - gpio_bit_reset(port, pin); + for (volatile uint32_t i = 0; i < ms * 4000U; i++) + ; } static void led_pattern(uint8_t p) { - led_off(LED1_PORT, LED1_PIN); - led_off(LED2_PORT, LED2_PIN); - led_off(LED3_PORT, LED3_PIN); - led_off(LED4_PORT, LED4_PIN); - if (p & 0x01) led_on(LED1_PORT, LED1_PIN); - if (p & 0x02) led_on(LED2_PORT, LED2_PIN); - if (p & 0x04) led_on(LED3_PORT, LED3_PIN); - if (p & 0x08) led_on(LED4_PORT, LED4_PIN); -} - -static void init_leds(void) -{ - rcu_periph_clock_enable(RCU_GPIOA); - rcu_periph_clock_enable(RCU_GPIOE); - rcu_periph_clock_enable(RCU_GPIOG); - rcu_periph_clock_enable(RCU_GPIOD); - - gpio_mode_set(LED1_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED1_PIN); - gpio_output_options_set(LED1_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED1_PIN); - gpio_mode_set(LED2_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED2_PIN); - gpio_output_options_set(LED2_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED2_PIN); - gpio_mode_set(LED3_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED3_PIN); - gpio_output_options_set(LED3_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED3_PIN); - gpio_mode_set(LED4_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED4_PIN); - gpio_output_options_set(LED4_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED4_PIN); - - led_off(LED1_PORT, LED1_PIN); - led_off(LED2_PORT, LED2_PIN); - led_off(LED3_PORT, LED3_PIN); - led_off(LED4_PORT, LED4_PIN); + LedManager &lm = LedManager::instance(); + lm.led(0).off(); + lm.led(1).off(); + lm.led(2).off(); + lm.led(3).off(); + if (p & 0x01) + lm.led(0).on(); + if (p & 0x02) + lm.led(1).on(); + if (p & 0x04) + lm.led(2).on(); + if (p & 0x08) + lm.led(3).on(); } static void init_usart0(void) @@ -89,21 +54,32 @@ static void init_usart0(void) static void uart_putchar(char c) { usart_data_transmit(USART0, (uint8_t)c); - while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)); + while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) + ; } static void uart_puts(const char *s) { - while (*s) uart_putchar(*s++); + while (*s) + uart_putchar(*s++); } static void uart_putdec(uint32_t val) { char buf[16]; int idx = 0; - if (val == 0) { uart_puts("0"); return; } - while (val > 0) { buf[idx++] = '0' + (val % 10); val /= 10; } - while (idx > 0) uart_putchar(buf[--idx]); + if (val == 0) + { + uart_puts("0"); + return; + } + while (val > 0) + { + buf[idx++] = '0' + (val % 10); + val /= 10; + } + while (idx > 0) + uart_putchar(buf[--idx]); } static void reinit_usart0_168m(void) @@ -121,7 +97,8 @@ static void test_sdram_driver(void) SdramManager &sdram = SdramManager::instance(); RetCode ret = sdram.init(); - if (ret != RET_OK) { + if (ret != RET_OK) + { printf(" SDRAM 初始化失败: 错误码=%d\r\n", ret); return; } @@ -134,10 +111,12 @@ static void test_sdram_driver(void) delay_1ms(1); bool diag1_ok = true; - for (uint32_t i = 0; i < 8; i++) { + for (uint32_t i = 0; i < 8; i++) + { uint16_t val = sram16[i]; uint16_t expected = (uint16_t)(0xAA00 + i); - if (val != expected) { + if (val != expected) + { printf(" 16位错误 @ [%lu]: 期望=0x%04X, 读取=0x%04X\r\n", i, expected, val); diag1_ok = false; } @@ -154,11 +133,14 @@ static void test_sdram_driver(void) delay_1ms(1); bool diag2_ok = true; - for (uint32_t i = 0; i < 4; i++) { + for (uint32_t i = 0; i < 4; i++) + { uint32_t val = sram32[i]; uint32_t expected = (i == 0) ? 0xDEADBEEF : (i == 1) ? 0xCAFEBABE - : (i == 2) ? 0x12345678 : 0x87654321; - if (val != expected) { + : (i == 2) ? 0x12345678 + : 0x87654321; + if (val != expected) + { printf(" 32位错误 @ [%lu]: 期望=0x%08lX, 读取=0x%08lX\r\n", i, expected, val); diag2_ok = false; } @@ -169,9 +151,12 @@ static void test_sdram_driver(void) uint32_t write_val = 0xA5A55A5A; uint32_t read_val = 0; ret = sdram.write(64, &write_val, sizeof(write_val)); - if (ret != RET_OK) { + if (ret != RET_OK) + { printf(" 驱动写入失败: %d\r\n", ret); - } else { + } + else + { __DSB(); ret = sdram.read(64, &read_val, sizeof(read_val)); if (ret != RET_OK) @@ -190,7 +175,8 @@ static void test_flash_driver(void) FlashManager &flash = FlashManager::instance(); RetCode ret = flash.init(); - if (ret != RET_OK) { + if (ret != RET_OK) + { printf(" Flash 初始化失败: %d\r\n", ret); return; } @@ -208,32 +194,49 @@ static void test_flash_driver(void) printf(" 擦除 Flash 扇区...\r\n"); ret = flash.erase(test_address, flash.sector_size()); - if (ret != RET_OK) { printf(" Flash 擦除失败: 错误码=%d\r\n", ret); return; } + if (ret != RET_OK) + { + printf(" Flash 擦除失败: 错误码=%d\r\n", ret); + return; + } printf(" Flash 擦除成功\r\n"); printf(" 写入 Flash 数据...\r\n"); ret = flash.write(test_address, write_buffer, sizeof(write_buffer)); - if (ret != RET_OK) { printf(" Flash 写入失败: %d\r\n", ret); return; } + if (ret != RET_OK) + { + printf(" Flash 写入失败: %d\r\n", ret); + return; + } printf(" Flash 写入成功\r\n"); printf(" 读取 Flash 数据...\r\n"); ret = flash.read(test_address, read_buffer, sizeof(read_buffer)); - if (ret != RET_OK) { printf(" Flash 读取失败: %d\r\n", ret); return; } + if (ret != RET_OK) + { + printf(" Flash 读取失败: %d\r\n", ret); + return; + } printf(" Flash 读取成功\r\n"); bool verify_ok = true; - for (int i = 0; i < 256; i++) { - if (read_buffer[i] != write_buffer[i]) { + for (int i = 0; i < 256; i++) + { + if (read_buffer[i] != write_buffer[i]) + { verify_ok = false; printf(" 数据错误 @ %d: 写入=%02X, 读取=%02X\r\n", i, write_buffer[i], read_buffer[i]); break; } } - if (verify_ok) printf(" Flash 数据验证成功\r\n"); + if (verify_ok) + printf(" Flash 数据验证成功\r\n"); ret = flash.self_test(256); - if (ret == RET_OK) printf(" Flash 自测试通过\r\n"); - else printf(" Flash 自测试失败: %d\r\n", ret); + if (ret == RET_OK) + printf(" Flash 自测试通过\r\n"); + else + printf(" Flash 自测试失败: %d\r\n", ret); printf("Flash 驱动测试完成\r\n"); } @@ -249,7 +252,8 @@ static void test_lcd(void) delay_1ms(500); uint16_t bands[4] = {Lcd::RED, Lcd::GREEN, Lcd::BLUE, Lcd::WHITE}; - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { int y0 = i * 200; int y1 = y0 + 199; lcd.blockWrite(0, 479, y0, y1); @@ -279,10 +283,12 @@ static void test_sdram_after_lcd(void) bool ok = true; volatile uint16_t *sram16 = (volatile uint16_t *)0xC0000000; - for (uint32_t i = 0; i < 8; i++) { + for (uint32_t i = 0; i < 8; i++) + { uint16_t val = sram16[i]; uint16_t expected = (uint16_t)(0xAA00 + i); - if (val != expected) { + if (val != expected) + { printf(" 16位错误 @ [%lu]: 期望=0x%04X, 读取=0x%04X\r\n", i, expected, val); ok = false; } @@ -290,9 +296,11 @@ static void test_sdram_after_lcd(void) volatile uint32_t *sram32 = (volatile uint32_t *)0xC0000000; uint32_t expected_32[4] = {0xDEADBEEF, 0xCAFEBABE, 0x12345678, 0x87654321}; - for (uint32_t i = 0; i < 4; i++) { + for (uint32_t i = 0; i < 4; i++) + { uint32_t val = sram32[i]; - if (val != expected_32[i]) { + if (val != expected_32[i]) + { printf(" 32位错误 @ [%lu]: 期望=0x%08lX, 读取=0x%08lX\r\n", i, expected_32[i], val); ok = false; } @@ -312,17 +320,18 @@ static void concurrent_loop(void) uint32_t counter = 0; volatile uint16_t *sram16 = (volatile uint16_t *)0xC0000000; - for (int iter = 0; iter < 10; iter++) { - led_on(LED1_PORT, LED1_PIN); - led_off(LED2_PORT, LED2_PIN); + for (int iter = 0; iter < 10; iter++) + { + LedManager::instance().led(0).on(); + LedManager::instance().led(1).off(); sram16[100 + iter] = (uint16_t)(iter * 0x1111); __DSB(); uint16_t val = sram16[100 + iter]; printf("[并发] iter=%d, SDRAM[%d]=0x%04X, LED1=ON\r\n", iter, 100 + iter, val); delay_1ms(500); - led_off(LED1_PORT, LED1_PIN); - led_on(LED2_PORT, LED2_PIN); + LedManager::instance().led(0).off(); + LedManager::instance().led(1).on(); sram16[200 + iter] = (uint16_t)(iter * 0x2222); __DSB(); val = sram16[200 + iter]; @@ -345,18 +354,19 @@ static void test_touch(void) printf("\r\n===== Touch 测试 (多点触控) =====\r\n"); RetCode ret = touch.init(); - if (ret != RET_OK) { + if (ret != RET_OK) + { printf(" Touch 初始化失败 (ret=%d)\r\n", ret); return; } printf(" Touch 初始化成功,等待触摸中断...\r\n"); static const uint16_t TP_COLORS[5] = { - 0xFFE0, // YELLOW - point 0 - 0x07FF, // CYAN - point 1 - 0xF81F, // MAGENTA - point 2 - 0x07E0, // GREEN - point 3 - 0xF800 // RED - point 4 + 0xFFE0, // YELLOW - point 0 + 0x07FF, // CYAN - point 1 + 0xF81F, // MAGENTA - point 2 + 0x07E0, // GREEN - point 3 + 0xF800 // RED - point 4 }; const uint16_t BG_COLOR = 0x0841; @@ -367,7 +377,8 @@ static void test_touch(void) lcd.setForeground(Lcd::WHITE); lcd.showString(10, 30, 460, 24, 16, 0, (uint8_t *)"Touch with up to 5 fingers"); - for (uint8_t i = 0; i < GT1151::kMaxTouch; i++) { + for (uint8_t i = 0; i < GT1151::kMaxTouch; i++) + { lcd.setForeground(TP_COLORS[i]); char lbl[8]; sprintf(lbl, "P%d: --", i); @@ -377,7 +388,8 @@ static void test_touch(void) uint16_t last_x[5]; uint16_t last_y[5]; bool was_active[5]; - for (uint8_t i = 0; i < GT1151::kMaxTouch; i++) { + for (uint8_t i = 0; i < GT1151::kMaxTouch; i++) + { last_x[i] = 0xFFFF; last_y[i] = 0xFFFF; was_active[i] = false; @@ -386,8 +398,10 @@ static void test_touch(void) uint32_t idle_counter = 0; GT1151::irq_flag = 0; - while (1) { - if (GT1151::irq_flag) { + while (1) + { + if (GT1151::irq_flag) + { GT1151::irq_flag = 0; delay_1ms(5); @@ -399,21 +413,25 @@ static void test_touch(void) uint8_t active_cnt = touch.activeCount(); uint8_t mask = sta & 0x1F; - for (uint8_t i = 0; i < GT1151::kMaxTouch; i++) { + for (uint8_t i = 0; i < GT1151::kMaxTouch; i++) + { bool active = (mask & (1 << i)) != 0; - if (active) { + if (active) + { uint16_t x = touch.x(i); uint16_t y = touch.y(i); - if (x < lcd.width() && y < lcd.height()) { + if (x < lcd.width() && y < lcd.height()) + { lcd.setForeground(TP_COLORS[i]); char buf[20]; sprintf(buf, "P%d: X:%-3d Y:%-3d", i, x, y); lcd.fillRectangle(10, 52 + i * 18, 200, 52 + i * 18 + 17); lcd.showString(10, 52 + i * 18, 200, 18, 16, 0, (uint8_t *)buf); - if (was_active[i] && last_x[i] != 0xFFFF) { + if (was_active[i] && last_x[i] != 0xFFFF) + { lcd.setForeground(TP_COLORS[i]); lcd.drawLine(last_x[i], last_y[i], x, y); } @@ -425,8 +443,11 @@ static void test_touch(void) last_y[i] = y; was_active[i] = true; } - } else { - if (was_active[i]) { + } + else + { + if (was_active[i]) + { lcd.setForeground(BG_COLOR); lcd.fillCircle(last_x[i], last_y[i], 6); @@ -442,15 +463,19 @@ static void test_touch(void) } printf("[TOUCH] cnt=%d sta=0x%02X", active_cnt, sta); - for (uint8_t i = 0; i < GT1151::kMaxTouch; i++) { + for (uint8_t i = 0; i < GT1151::kMaxTouch; i++) + { if (mask & (1 << i)) printf(" P%d(%u,%u)", i, touch.x(i), touch.y(i)); } printf("\r\n"); - } else { + } + else + { idle_counter++; delay_1ms(10); - if (idle_counter > 500) { + if (idle_counter > 500) + { printf(" 无触摸超过 5 秒,退出 Touch 测试\r\n"); break; } @@ -464,7 +489,7 @@ static void test_touch(void) int main(void) { - init_leds(); + LedManager::instance().init_all(); led_pattern(0x01); init_usart0(); @@ -475,18 +500,23 @@ int main(void) uint32_t cs = RCU_CFG0 & RCU_CFG0_SCS; uart_puts("Clock source: "); - if (cs == RCU_SCSS_IRC16M) uart_puts("IRC16M (16MHz)\r\n"); - else if (cs == RCU_SCSS_HXTAL) uart_puts("HXTAL (25MHz)\r\n"); - else if (cs == RCU_SCSS_PLLP) uart_puts("PLL (168MHz)\r\n"); - else uart_puts("UNKNOWN\r\n"); + if (cs == RCU_SCSS_IRC16M) + uart_puts("IRC16M (16MHz)\r\n"); + else if (cs == RCU_SCSS_HXTAL) + uart_puts("HXTAL (25MHz)\r\n"); + else if (cs == RCU_SCSS_PLLP) + uart_puts("PLL (168MHz)\r\n"); + else + uart_puts("UNKNOWN\r\n"); uart_puts("SystemCoreClock: "); uart_putdec(SystemCoreClock); uart_puts(" Hz\r\n"); - for (int i = 0; i < 3; i++) { - led_on(LED2_PORT, LED2_PIN); + for (int i = 0; i < 3; i++) + { + LedManager::instance().led(1).on(); delay_16m(200); - led_off(LED2_PORT, LED2_PIN); + LedManager::instance().led(1).off(); delay_16m(200); } uart_puts("LED blink OK\r\n"); @@ -500,17 +530,15 @@ int main(void) cs = RCU_CFG0 & RCU_CFG0_SCS; uart_puts("Clock after init: "); - if (cs == RCU_SCSS_PLLP) uart_puts("PLL (168MHz)\r\n"); - else uart_puts("UNKNOWN\r\n"); + if (cs == RCU_SCSS_PLLP) + uart_puts("PLL (168MHz)\r\n"); + else + uart_puts("UNKNOWN\r\n"); uart_puts("SystemCoreClock: "); uart_putdec(SystemCoreClock); uart_puts(" Hz\r\n"); led_pattern(0x07); - LedManager::instance().init_all(); - LedManager::instance().led(1).on(); - delay_16m(100); - LedManager::instance().led(1).off(); uart_puts("LedManager OK\r\n"); led_pattern(0x09); @@ -554,10 +582,11 @@ int main(void) printf("系统运行于 168MHz, Flash/SDRAM/LCD/UART/LED 全部正常\r\n"); uint32_t tick = 0; - while (1) { - led_on(LED4_PORT, LED4_PIN); + while (1) + { + LedManager::instance().led(3).on(); delay_1ms(250); - led_off(LED4_PORT, LED4_PIN); + LedManager::instance().led(3).off(); delay_1ms(250); tick++; diff --git a/bsp/device/sdram/sdram_driver.cpp b/bsp/device/sdram/sdram_driver.cpp deleted file mode 100644 index aa4f0df..0000000 --- a/bsp/device/sdram/sdram_driver.cpp +++ /dev/null @@ -1,699 +0,0 @@ -#include "sdram_driver.h" -#include "exmc_driver.h" -#include "config.h" -#include "systick.h" -#include -#include -#include - -/* SDRAM模式寄存器定义 */ -#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) -#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) -#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) -#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0003) -#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) -#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) -#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) -#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) -#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) -#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) -#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) - -/* SDRAM设备基地址定义 */ -#define SDRAM_DEVICE0_BASE_ADDR ((uint32_t)0xC0000000) -#define SDRAM_DEVICE1_BASE_ADDR ((uint32_t)0xD0000000) - -/* SDRAM超时定义 */ -#define SDRAM_TIMEOUT ((uint32_t)0x0000FFFF) - -/* 私有数据结构体 */ -typedef struct -{ - uint32_t base_address; /* SDRAM基地址 */ - bool initialized; /* 初始化标志 */ -} sdram_private_t; - -/* 默认SDRAM配置(参照官方示例优化) */ -static const sdram_config_t default_sdram_config = { - .column_address_width = EXMC_SDRAM_COW_ADDRESS_9, - .row_address_width = EXMC_SDRAM_ROW_ADDRESS_13, - .data_width = EXMC_SDRAM_DATABUS_WIDTH_16B, - .internal_bank_number = EXMC_SDRAM_4_INTER_BANK, - .cas_latency = EXMC_CAS_LATENCY_3_SDCLK, - .write_protection = false, - .sdclock_config = EXMC_SDCLK_PERIODS_3_HCLK, - .burst_read_switch = true, - .pipeline_read_delay = EXMC_PIPELINE_DELAY_1_HCLK, - .timing = { - .load_mode_register_delay = 2, - .exit_selfrefresh_delay = 7, - .row_address_select_delay = 5, - .auto_refresh_delay = 6, - .write_recovery_delay = 2, - .row_precharge_delay = 2, - .row_to_column_delay = 2, - }}; - -/* 全局SDRAM句柄(用于默认初始化) */ -static sdram_handle_t default_sdram_handle = { - .device = SDRAM_DEVICE_0, - .config = default_sdram_config, - .private_data = NULL}; - -/* 私有数据实例 */ -static sdram_private_t sdram_private[SDRAM_DEVICE_MAX]; - -/** - * @brief 获取EXMC SDRAM设备枚举值 - * @param device SDRAM设备类型 - * @return EXMC SDRAM设备值 - */ -static uint32_t get_exmc_sdram_device(sdram_device_t device) -{ - switch (device) - { - case SDRAM_DEVICE_0: - return EXMC_SDRAM_DEVICE0; - case SDRAM_DEVICE_1: - return EXMC_SDRAM_DEVICE1; - default: - return EXMC_SDRAM_DEVICE0; - } -} - -/** - * @brief 获取EXMC SDRAM设备选择值 - * @param device SDRAM设备类型 - * @return EXMC SDRAM设备选择值 - */ -static uint32_t get_exmc_sdram_bank_select(sdram_device_t device) -{ - switch (device) - { - case SDRAM_DEVICE_0: - return EXMC_SDRAM_DEVICE0_SELECT; - case SDRAM_DEVICE_1: - return EXMC_SDRAM_DEVICE1_SELECT; - default: - return EXMC_SDRAM_DEVICE0_SELECT; - } -} - - - -/** - * @brief 执行SDRAM初始化序列 - * @param exmc_device EXMC SDRAM设备 - * @param bank_select EXMC SDRAM设备选择 - * @param config SDRAM配置 - * @return 操作结果 - */ -static ret_code_t execute_sdram_init_sequence(uint32_t exmc_device, uint32_t bank_select, const sdram_config_t *config) -{ - 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 timeout = SDRAM_TIMEOUT; - uint32_t command_content; - - printf("[SDRAM] 开始执行初始化序列 (设备: 0x%08lX, Bank: 0x%08lX)\r\n", exmc_device, bank_select); - - /* 步骤1:配置SDRAM时序寄存器 */ - printf("[SDRAM] 步骤1: 配置时序寄存器...\r\n"); - sdram_timing_init_struct.load_mode_register_delay = config->timing.load_mode_register_delay; - sdram_timing_init_struct.exit_selfrefresh_delay = config->timing.exit_selfrefresh_delay; - sdram_timing_init_struct.row_address_select_delay = config->timing.row_address_select_delay; - sdram_timing_init_struct.auto_refresh_delay = config->timing.auto_refresh_delay; - sdram_timing_init_struct.write_recovery_delay = config->timing.write_recovery_delay; - sdram_timing_init_struct.row_precharge_delay = config->timing.row_precharge_delay; - sdram_timing_init_struct.row_to_column_delay = config->timing.row_to_column_delay; - - printf("[SDRAM] 时序参数: LMRD=%ld, XSRD=%ld, RASD=%ld, ARFD=%ld, WRD=%ld, RPD=%ld, RCD=%ld\r\n", - sdram_timing_init_struct.load_mode_register_delay, - sdram_timing_init_struct.exit_selfrefresh_delay, - sdram_timing_init_struct.row_address_select_delay, - sdram_timing_init_struct.auto_refresh_delay, - sdram_timing_init_struct.write_recovery_delay, - sdram_timing_init_struct.row_precharge_delay, - sdram_timing_init_struct.row_to_column_delay); - - /* 步骤2:配置SDRAM控制寄存器 */ - printf("[SDRAM] 步骤2: 配置控制寄存器...\r\n"); - sdram_init_struct.sdram_device = exmc_device; - sdram_init_struct.column_address_width = config->column_address_width; - sdram_init_struct.row_address_width = config->row_address_width; - sdram_init_struct.data_width = config->data_width; - sdram_init_struct.internal_bank_number = config->internal_bank_number; - sdram_init_struct.cas_latency = config->cas_latency; - sdram_init_struct.write_protection = config->write_protection ? ENABLE : DISABLE; - sdram_init_struct.sdclock_config = config->sdclock_config; - sdram_init_struct.burst_read_switch = config->burst_read_switch ? ENABLE : DISABLE; - sdram_init_struct.pipeline_read_delay = config->pipeline_read_delay; - sdram_init_struct.timing = &sdram_timing_init_struct; - - /* EXMC SDRAM Bank初始化 */ - printf("[SDRAM] 执行EXMC SDRAM初始化...\r\n"); - exmc_sdram_init(&sdram_init_struct); - printf("[SDRAM] EXMC SDRAM初始化完成\r\n"); - - /* 步骤3:配置CKE高电平命令 */ - 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_2_SDCLK; - sdram_command_init_struct.mode_register_content = 0; - - /* 等待SDRAM控制器就绪 */ - timeout = SDRAM_TIMEOUT; - while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) - { - timeout--; - } - if (timeout == 0) - { - return RET_TIMEOUT; - } - - /* 发送命令 */ - exmc_sdram_command_config(&sdram_command_init_struct); - - /* 步骤4:插入10ms延时 */ - delay_1ms(10); - - /* 步骤5:配置预充电所有命令 */ - 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_2_SDCLK; - sdram_command_init_struct.mode_register_content = 0; - - timeout = SDRAM_TIMEOUT; - while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) - { - timeout--; - } - if (timeout == 0) - { - return RET_TIMEOUT; - } - - exmc_sdram_command_config(&sdram_command_init_struct); - - /* 步骤6:配置自动刷新命令 */ - 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_9_SDCLK; - sdram_command_init_struct.mode_register_content = 0; - - timeout = SDRAM_TIMEOUT; - while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) - { - timeout--; - } - if (timeout == 0) - { - return RET_TIMEOUT; - } - - exmc_sdram_command_config(&sdram_command_init_struct); - - /* 步骤7:配置加载模式寄存器命令 */ - /* 编程模式寄存器 */ - 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_2_SDCLK; - sdram_command_init_struct.mode_register_content = command_content; - - timeout = SDRAM_TIMEOUT; - while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) - { - timeout--; - } - if (timeout == 0) - { - return RET_TIMEOUT; - } - - exmc_sdram_command_config(&sdram_command_init_struct); - - /* 步骤8:设置自动刷新速率计数器 */ - /* 64ms, 8192-cycle refresh, 64ms/8192=7.81us */ - /* SDCLK_Freq = HCLK/3 = 168MHz/3 = 56MHz */ - /* (7.81 us * 56MHz) - 20 ≈ 418 */ - exmc_sdram_refresh_count_set(418); - - /* 等待SDRAM控制器就绪 */ - timeout = SDRAM_TIMEOUT; - while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) - { - timeout--; - } - if (timeout == 0) - { - return RET_TIMEOUT; - } - - /* 步骤9:配置读采样(解决读取数据为0的问题) */ - /* 读采样延迟链补偿 PCB 走线延迟,确保 EXMC 在正确的时钟边沿采样数据 */ - exmc_sdram_readsample_enable(ENABLE); - exmc_sdram_readsample_config(EXMC_SDRAM_4_DELAY_CELL, EXMC_SDRAM_READSAMPLE_0_EXTRAHCLK); - - return RET_OK; -} - -/* 公共函数实现 */ - -ret_code_t sdram_init(sdram_handle_t *handle) -{ - if (handle == NULL || handle->device >= SDRAM_DEVICE_MAX) - { - printf("[SDRAM] 初始化失败: 无效参数\r\n"); - return RET_INVALID_PARAM; - } - - printf("[SDRAM] 开始初始化设备 %d\r\n", handle->device); - - /* 初始化私有数据 */ - sdram_private_t *priv = &sdram_private[handle->device]; - - /* 获取SDRAM基地址 */ - switch (handle->device) - { - case SDRAM_DEVICE_0: - priv->base_address = SDRAM_DEVICE0_BASE_ADDR; - printf("[SDRAM] 使用设备0,基地址: 0x%08lX\r\n", priv->base_address); - break; - case SDRAM_DEVICE_1: - priv->base_address = SDRAM_DEVICE1_BASE_ADDR; - printf("[SDRAM] 使用设备1,基地址: 0x%08lX\r\n", priv->base_address); - break; - default: - printf("[SDRAM] 初始化失败: 无效设备 %d\r\n", handle->device); - return RET_INVALID_PARAM; - } - - /* 显示配置信息 */ - printf("[SDRAM] 配置信息:\r\n"); - printf(" 列地址宽度: %d\r\n", handle->config.column_address_width == EXMC_SDRAM_COW_ADDRESS_9 ? 9 : 8); - printf(" 行地址宽度: %d\r\n", handle->config.row_address_width == EXMC_SDRAM_ROW_ADDRESS_13 ? 13 : 12); - printf(" 数据宽度: %d位\r\n", handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B ? 16 : (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B ? 8 : 32)); - printf(" 内部Bank数: %d\r\n", handle->config.internal_bank_number == EXMC_SDRAM_4_INTER_BANK ? 4 : 2); - printf(" CAS延迟: %d个时钟\r\n", handle->config.cas_latency == EXMC_CAS_LATENCY_3_SDCLK ? 3 : 2); - printf(" 写保护: %s\r\n", handle->config.write_protection ? "启用" : "禁用"); - printf(" SDCLK配置: HCLK/%d\r\n", handle->config.sdclock_config == EXMC_SDCLK_PERIODS_3_HCLK ? 3 : 2); - - /* 初始化EXMC总线(时钟 + 共享数据引脚 + SDRAM专用引脚) */ - ExmcBus &exmc_bus = ExmcBus::instance(); - exmc_bus.init(); - ExmcBus::sdram_pin_init(); - printf("[SDRAM] EXMC总线初始化完成\r\n"); - - /* 获取EXMC设备参数 */ - uint32_t exmc_device = get_exmc_sdram_device(handle->device); - uint32_t bank_select = get_exmc_sdram_bank_select(handle->device); - printf("[SDRAM] EXMC设备: 0x%08lX, Bank选择: 0x%08lX\r\n", exmc_device, bank_select); - - /* 执行SDRAM初始化序列 */ - printf("[SDRAM] 开始执行初始化序列...\r\n"); - ret_code_t ret = execute_sdram_init_sequence(exmc_device, bank_select, &handle->config); - if (ret != RET_OK) - { - printf("[SDRAM] 初始化序列失败: 错误码=%d\r\n", ret); - return ret; - } - - /* 标记为已初始化 */ - priv->initialized = true; - handle->private_data = (void *)priv; - - printf("[SDRAM] 初始化成功完成\r\n"); - - return RET_OK; -} - -ret_code_t sdram_deinit(sdram_handle_t *handle) -{ - if (handle == NULL || handle->device >= SDRAM_DEVICE_MAX) - { - return RET_INVALID_PARAM; - } - - sdram_private_t *priv = (sdram_private_t *)handle->private_data; - if (priv == NULL || !priv->initialized) - { - return RET_NOT_INITIALIZED; - } - - /* 禁用SDRAM控制器(通过禁用EXMC时钟) */ - /* 注意:这会影响其他EXMC外设,实际项目中可能需要更精细的控制 */ - rcu_periph_clock_disable(RCU_EXMC); - - /* 标记为未初始化 */ - priv->initialized = false; - handle->private_data = NULL; - - return RET_OK; -} - -ret_code_t sdram_write(sdram_handle_t *handle, uint32_t address, const void *data, uint32_t length) -{ - if (handle == NULL || handle->device >= SDRAM_DEVICE_MAX || data == NULL) - { - return RET_INVALID_PARAM; - } - - sdram_private_t *priv = (sdram_private_t *)handle->private_data; - if (priv == NULL || !priv->initialized) - { - return RET_NOT_INITIALIZED; - } - - if (length == 0) - { - return RET_OK; - } - - /* 计算实际内存地址 */ - uint32_t mem_addr = priv->base_address + address; - - /* 调试输出:显示写入信息 */ - if (length > 1) - { - printf("[SDRAM] 写入: 地址=0x%08lX, 长度=%lu, 数据宽度=%d位\r\n", - mem_addr, length, - (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B) ? 8 : (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) ? 16 - : 32); - if (length <= 16) - { - printf("[SDRAM] 数据: "); - const uint8_t *dbg_data = (const uint8_t *)data; - for (uint32_t i = 0; i < length && i < 16; i++) - { - printf("%02X ", dbg_data[i]); - } - printf("\r\n"); - } - } - - /* 根据数据宽度进行写入 */ - if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B) - { - uint8_t *dst = (uint8_t *)mem_addr; - const uint8_t *src = (const uint8_t *)data; - for (uint32_t i = 0; i < length; i++) - { - dst[i] = src[i]; - } - } - else if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) - { - volatile uint16_t *dst = (volatile uint16_t *)mem_addr; - const uint8_t *src = (const uint8_t *)data; - uint32_t halfword_len = length / 2; - for (uint32_t i = 0; i < halfword_len; i++) - { - dst[i] = (uint16_t)(src[i * 2] | ((uint16_t)src[i * 2 + 1] << 8)); - } - if (length & 1) - { - uint16_t last_word = dst[halfword_len]; - last_word = (last_word & 0xFF00) | src[length - 1]; - dst[halfword_len] = last_word; - } - __DSB(); - } - else if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_32B) - { - volatile uint32_t *dst = (volatile uint32_t *)mem_addr; - const uint32_t *src = (const uint32_t *)data; - uint32_t dword_len = length / 4; - for (uint32_t i = 0; i < dword_len; i++) - { - dst[i] = src[i]; - } - uint32_t remain = length % 4; - if (remain) - { - volatile uint8_t *dst8 = (volatile uint8_t *)&dst[dword_len]; - const uint8_t *src8 = (const uint8_t *)&src[dword_len]; - for (uint32_t i = 0; i < remain; i++) - { - dst8[i] = src8[i]; - } - } - } - else - { - return RET_NOT_SUPPORTED; - } - - /* 数据同步屏障,确保所有写入完成 */ - __DSB(); - - return RET_OK; -} - -ret_code_t sdram_read(sdram_handle_t *handle, uint32_t address, void *buffer, uint32_t length) -{ - if (handle == NULL || handle->device >= SDRAM_DEVICE_MAX || buffer == NULL) - { - return RET_INVALID_PARAM; - } - - sdram_private_t *priv = (sdram_private_t *)handle->private_data; - if (priv == NULL || !priv->initialized) - { - return RET_NOT_INITIALIZED; - } - - if (length == 0) - { - return RET_OK; - } - - /* 计算实际内存地址 */ - uint32_t mem_addr = priv->base_address + address; - - /* 根据数据宽度进行读取 */ - if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B) - { - uint8_t *src = (uint8_t *)mem_addr; - uint8_t *dst = (uint8_t *)buffer; - for (uint32_t i = 0; i < length; i++) - { - dst[i] = src[i]; - } - } - else if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) - { - __DSB(); - volatile uint16_t *src = (volatile uint16_t *)mem_addr; - uint8_t *dst = (uint8_t *)buffer; - uint32_t halfword_len = length / 2; - for (uint32_t i = 0; i < halfword_len; i++) - { - uint32_t val = src[i]; - dst[i * 2] = (uint8_t)(val & 0xFF); - dst[i * 2 + 1] = (uint8_t)((val >> 8) & 0xFF); - } - if (length & 1) - { - uint16_t val = src[halfword_len]; - dst[length - 1] = (uint8_t)(val & 0xFF); - } - __DSB(); - } - else if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_32B) - { - volatile uint32_t *src = (volatile uint32_t *)mem_addr; - uint32_t *dst = (uint32_t *)buffer; - uint32_t dword_len = length / 4; - for (uint32_t i = 0; i < dword_len; i++) - { - dst[i] = src[i]; - } - uint32_t remain = length % 4; - if (remain) - { - volatile uint8_t *src8 = (volatile uint8_t *)&src[dword_len]; - uint8_t *dst8 = (uint8_t *)&dst[dword_len]; - for (uint32_t i = 0; i < remain; i++) - { - dst8[i] = src8[i]; - } - } - } - else - { - return RET_NOT_SUPPORTED; - } - - /* 数据内存屏障,确保所有读取完成并按顺序执行 */ - __DMB(); - - return RET_OK; -} - -ret_code_t sdram_fill(sdram_handle_t *handle, uint32_t address, uint8_t value, uint32_t length) -{ - if (handle == NULL || handle->device >= SDRAM_DEVICE_MAX) - { - return RET_INVALID_PARAM; - } - - sdram_private_t *priv = (sdram_private_t *)handle->private_data; - if (priv == NULL || !priv->initialized) - { - return RET_NOT_INITIALIZED; - } - - if (length == 0) - { - return RET_OK; - } - - /* 计算实际内存地址 */ - uint32_t mem_addr = priv->base_address + address; - - /* 根据数据宽度进行填充 */ - if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B) - { - /* 8位填充 */ - uint8_t *dst = (uint8_t *)mem_addr; - for (uint32_t i = 0; i < length; i++) - { - dst[i] = value; - } - } - else if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) - { - /* 16位填充,需要处理地址对齐 */ - uint16_t word_value = (value << 8) | value; - uint8_t *dst8 = (uint8_t *)mem_addr; - uint16_t *dst16; - - /* 检查地址对齐 */ - if ((address & 0x1) != 0) - { - /* 地址未对齐,先填充第一个字节 */ - dst8[0] = value; - dst8++; - length--; - } - - /* 填充完整的16位字 */ - dst16 = (uint16_t *)dst8; - uint32_t word_count = length / 2; - for (uint32_t i = 0; i < word_count; i++) - { - dst16[i] = word_value; - } - - /* 处理剩余的单个字节(如果长度是奇数) */ - if (length & 0x1) - { - dst8 = (uint8_t *)&dst16[word_count]; - dst8[0] = value; - } - } - else if (handle->config.data_width == EXMC_SDRAM_DATABUS_WIDTH_32B) - { - /* 32位填充,需要地址对齐 */ - uint32_t dword_value = (value << 24) | (value << 16) | (value << 8) | value; - uint32_t *dst = (uint32_t *)mem_addr; - uint32_t dword_count = (length + 3) / 4; - for (uint32_t i = 0; i < dword_count; i++) - { - dst[i] = dword_value; - } - } - else - { - return RET_NOT_SUPPORTED; - } - - return RET_OK; -} - -ret_code_t sdram_self_test(sdram_handle_t *handle, uint32_t test_size) -{ - if (handle == NULL || handle->device >= SDRAM_DEVICE_MAX) - { - return RET_INVALID_PARAM; - } - - sdram_private_t *priv = (sdram_private_t *)handle->private_data; - if (priv == NULL || !priv->initialized) - { - return RET_NOT_INITIALIZED; - } - - /* 限制测试大小,避免超出SDRAM容量 */ - if (test_size > 1024 * 1024) - { - test_size = 1024 * 1024; - } - -/* 使用固定块大小进行测试,通过驱动API读写SDRAM */ -#define SELF_TEST_BLOCK_SIZE 256 - - ret_code_t ret; - uint8_t write_buf[SELF_TEST_BLOCK_SIZE]; - uint8_t read_buf[SELF_TEST_BLOCK_SIZE]; - - for (uint32_t offset = 0; offset < test_size; offset += SELF_TEST_BLOCK_SIZE) - { - uint32_t block_size = (test_size - offset) > SELF_TEST_BLOCK_SIZE ? SELF_TEST_BLOCK_SIZE : (test_size - offset); - - for (uint32_t i = 0; i < block_size; i++) - { - write_buf[i] = (uint8_t)((offset + i) & 0xFF); - } - - ret = sdram_write(handle, offset, write_buf, block_size); - if (ret != RET_OK) - { - return ret; - } - - ret = sdram_read(handle, offset, read_buf, block_size); - if (ret != RET_OK) - { - return ret; - } - - for (uint32_t i = 0; i < block_size; i++) - { - if (read_buf[i] != write_buf[i]) - { - return RET_ERROR; - } - } - } - - return RET_OK; -} - -uint32_t sdram_get_base_address(sdram_device_t device) -{ - switch (device) - { - case SDRAM_DEVICE_0: - return SDRAM_DEVICE0_BASE_ADDR; - case SDRAM_DEVICE_1: - return SDRAM_DEVICE1_BASE_ADDR; - default: - return 0; - } -} - -ret_code_t sdram_default_init(void) -{ - /* 使用默认句柄进行初始化 */ - return sdram_init(&default_sdram_handle); -} diff --git a/bsp/device/sdram/sdram_driver.h b/bsp/device/sdram/sdram_driver.h deleted file mode 100644 index 6251540..0000000 --- a/bsp/device/sdram/sdram_driver.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef __SDRAM_DRIVER_H__ -#define __SDRAM_DRIVER_H__ - -#include -#include "common_types.h" -#include "gd32f4xx.h" - -/* SDRAM设备类型定义 */ -typedef enum { - SDRAM_DEVICE_0 = 0, /* SDRAM设备0,基地址0xC0000000 */ - SDRAM_DEVICE_1 = 1, /* SDRAM设备1,基地址0xD0000000 */ - SDRAM_DEVICE_MAX -} sdram_device_t; - -/* SDRAM配置结构体 */ -typedef struct { - uint32_t column_address_width; /* 列地址宽度: 8, 9, 10, 11, 12位 */ - uint32_t row_address_width; /* 行地址宽度: 11, 12, 13位 */ - uint32_t data_width; /* 数据总线宽度: 8, 16, 32位 */ - uint32_t internal_bank_number; /* 内部Bank数量: 2或4 */ - uint32_t cas_latency; /* CAS延迟: 1, 2, 3个时钟周期 */ - bool write_protection; /* 写保护使能 */ - uint32_t sdclock_config; /* SDCLK配置: HCLK分频 */ - bool burst_read_switch; /* 突发读取开关 */ - uint32_t pipeline_read_delay; /* 流水线读取延迟: 0, 1, 2个HCLK */ - - /* 时序参数 */ - struct { - uint32_t load_mode_register_delay; /* 加载模式寄存器延迟 (LMRD) */ - uint32_t exit_selfrefresh_delay; /* 退出自刷新延迟 (XSRD) */ - uint32_t row_address_select_delay; /* 行地址选择延迟 (RASD) */ - uint32_t auto_refresh_delay; /* 自动刷新延迟 (ARFD) */ - uint32_t write_recovery_delay; /* 写恢复延迟 (WRD) */ - uint32_t row_precharge_delay; /* 行预充电延迟 (RPD) */ - uint32_t row_to_column_delay; /* 行到列延迟 (RCD) */ - } timing; -} sdram_config_t; - -/* SDRAM句柄结构体 */ -typedef struct { - sdram_device_t device; /* SDRAM设备 */ - sdram_config_t config; /* SDRAM配置 */ - void *private_data; /* 私有数据指针 */ -} sdram_handle_t; - -/* 函数声明 */ - -/** - * @brief 初始化SDRAM - * @param handle SDRAM句柄指针 - * @return 操作结果 - */ -ret_code_t sdram_init(sdram_handle_t *handle); - -/** - * @brief 反初始化SDRAM - * @param handle SDRAM句柄指针 - * @return 操作结果 - */ -ret_code_t sdram_deinit(sdram_handle_t *handle); - -/** - * @brief 写入数据到SDRAM - * @param handle SDRAM句柄指针 - * @param address 相对地址(从SDRAM基地址开始的偏移) - * @param data 数据指针 - * @param length 数据长度(字节) - * @return 操作结果 - */ -ret_code_t sdram_write(sdram_handle_t *handle, uint32_t address, const void *data, uint32_t length); - -/** - * @brief 从SDRAM读取数据 - * @param handle SDRAM句柄指针 - * @param address 相对地址(从SDRAM基地址开始的偏移) - * @param buffer 缓冲区指针 - * @param length 数据长度(字节) - * @return 操作结果 - */ -ret_code_t sdram_read(sdram_handle_t *handle, uint32_t address, void *buffer, uint32_t length); - -/** - * @brief 填充SDRAM区域 - * @param handle SDRAM句柄指针 - * @param address 起始地址 - * @param value 填充值 - * @param length 填充长度(字节) - * @return 操作结果 - */ -ret_code_t sdram_fill(sdram_handle_t *handle, uint32_t address, uint8_t value, uint32_t length); - -/** - * @brief 验证SDRAM读写功能 - * @param handle SDRAM句柄指针 - * @param test_size 测试数据大小(字节) - * @return 操作结果 - */ -ret_code_t sdram_self_test(sdram_handle_t *handle, uint32_t test_size); - -/** - * @brief 获取SDRAM基地址 - * @param device SDRAM设备 - * @return SDRAM基地址,如果设备无效返回0 - */ -uint32_t sdram_get_base_address(sdram_device_t device); - -/** - * @brief 默认SDRAM初始化(使用预定义配置) - * @return 操作结果 - */ -ret_code_t sdram_default_init(void); - -#endif /* __SDRAM_DRIVER_H__ */ \ No newline at end of file diff --git a/bsp/device/sdram/sdram_manager.cpp b/bsp/device/sdram/sdram_manager.cpp index d24e48d..4a55952 100644 --- a/bsp/device/sdram/sdram_manager.cpp +++ b/bsp/device/sdram/sdram_manager.cpp @@ -1,6 +1,27 @@ #include "sdram_manager.h" -#include +#include "exmc_driver.h" +#include "config.h" +#include "systick.h" +#include #include +#include + +#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) +#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) +#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0003) +#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) +#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) +#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) +#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) +#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) + +#define SDRAM_DEVICE0_BASE_ADDR ((uint32_t)0xC0000000) +#define SDRAM_DEVICE1_BASE_ADDR ((uint32_t)0xD0000000) + +#define SDRAM_TIMEOUT ((uint32_t)0x0000FFFF) SdramManager &SdramManager::instance() { @@ -9,31 +30,200 @@ SdramManager &SdramManager::instance() } SdramManager::SdramManager() - : handle_{ - .device = SDRAM_DEVICE_0, - .config = { - .column_address_width = EXMC_SDRAM_COW_ADDRESS_9, - .row_address_width = EXMC_SDRAM_ROW_ADDRESS_13, - .data_width = EXMC_SDRAM_DATABUS_WIDTH_16B, - .internal_bank_number = EXMC_SDRAM_4_INTER_BANK, - .cas_latency = EXMC_CAS_LATENCY_3_SDCLK, - .write_protection = false, - .sdclock_config = EXMC_SDCLK_PERIODS_3_HCLK, - .burst_read_switch = true, - .pipeline_read_delay = EXMC_PIPELINE_DELAY_2_HCLK, - .timing = { - .load_mode_register_delay = 2, - .exit_selfrefresh_delay = 7, - .row_address_select_delay = 5, - .auto_refresh_delay = 6, - .write_recovery_delay = 2, - .row_precharge_delay = 2, - .row_to_column_delay = 2, - }}, - .private_data = nullptr} + : config_{ + .column_address_width = EXMC_SDRAM_COW_ADDRESS_9, + .row_address_width = EXMC_SDRAM_ROW_ADDRESS_13, + .data_width = EXMC_SDRAM_DATABUS_WIDTH_16B, + .internal_bank_number = EXMC_SDRAM_4_INTER_BANK, + .cas_latency = EXMC_CAS_LATENCY_3_SDCLK, + .write_protection = false, + .sdclock_config = EXMC_SDCLK_PERIODS_3_HCLK, + .burst_read_switch = true, + .pipeline_read_delay = EXMC_PIPELINE_DELAY_1_HCLK, + .timing = { + .load_mode_register_delay = 2, + .exit_selfrefresh_delay = 7, + .row_address_select_delay = 5, + .auto_refresh_delay = 6, + .write_recovery_delay = 2, + .row_precharge_delay = 2, + .row_to_column_delay = 2, + }}, + base_addr_(SDRAM_DEVICE0_BASE_ADDR) { } +uint32_t SdramManager::base_address() const +{ + return base_addr_; +} + +uint32_t SdramManager::getExmcDevice() const +{ + switch (device_) + { + case DEVICE_0: + return EXMC_SDRAM_DEVICE0; + case DEVICE_1: + return EXMC_SDRAM_DEVICE1; + default: + return EXMC_SDRAM_DEVICE0; + } +} + +uint32_t SdramManager::getExmcBankSelect() const +{ + switch (device_) + { + case DEVICE_0: + return EXMC_SDRAM_DEVICE0_SELECT; + case DEVICE_1: + return EXMC_SDRAM_DEVICE1_SELECT; + default: + return EXMC_SDRAM_DEVICE0_SELECT; + } +} + +RetCode SdramManager::executeInitSequence(uint32_t exmc_device, uint32_t bank_select) +{ + 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 timeout = SDRAM_TIMEOUT; + uint32_t command_content; + + printf("[SDRAM] 开始执行初始化序列 (设备: 0x%08lX, Bank: 0x%08lX)\r\n", exmc_device, bank_select); + + printf("[SDRAM] 步骤1: 配置时序寄存器...\r\n"); + sdram_timing_init_struct.load_mode_register_delay = config_.timing.load_mode_register_delay; + sdram_timing_init_struct.exit_selfrefresh_delay = config_.timing.exit_selfrefresh_delay; + sdram_timing_init_struct.row_address_select_delay = config_.timing.row_address_select_delay; + sdram_timing_init_struct.auto_refresh_delay = config_.timing.auto_refresh_delay; + sdram_timing_init_struct.write_recovery_delay = config_.timing.write_recovery_delay; + sdram_timing_init_struct.row_precharge_delay = config_.timing.row_precharge_delay; + sdram_timing_init_struct.row_to_column_delay = config_.timing.row_to_column_delay; + + printf("[SDRAM] 时序参数: LMRD=%ld, XSRD=%ld, RASD=%ld, ARFD=%ld, WRD=%ld, RPD=%ld, RCD=%ld\r\n", + sdram_timing_init_struct.load_mode_register_delay, + sdram_timing_init_struct.exit_selfrefresh_delay, + sdram_timing_init_struct.row_address_select_delay, + sdram_timing_init_struct.auto_refresh_delay, + sdram_timing_init_struct.write_recovery_delay, + sdram_timing_init_struct.row_precharge_delay, + sdram_timing_init_struct.row_to_column_delay); + + printf("[SDRAM] 步骤2: 配置控制寄存器...\r\n"); + sdram_init_struct.sdram_device = exmc_device; + sdram_init_struct.column_address_width = config_.column_address_width; + sdram_init_struct.row_address_width = config_.row_address_width; + sdram_init_struct.data_width = config_.data_width; + sdram_init_struct.internal_bank_number = config_.internal_bank_number; + sdram_init_struct.cas_latency = config_.cas_latency; + sdram_init_struct.write_protection = config_.write_protection ? ENABLE : DISABLE; + sdram_init_struct.sdclock_config = config_.sdclock_config; + sdram_init_struct.burst_read_switch = config_.burst_read_switch ? ENABLE : DISABLE; + sdram_init_struct.pipeline_read_delay = config_.pipeline_read_delay; + sdram_init_struct.timing = &sdram_timing_init_struct; + + printf("[SDRAM] 执行EXMC SDRAM初始化...\r\n"); + exmc_sdram_init(&sdram_init_struct); + printf("[SDRAM] EXMC SDRAM初始化完成\r\n"); + + 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_2_SDCLK; + sdram_command_init_struct.mode_register_content = 0; + + timeout = SDRAM_TIMEOUT; + while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) + { + timeout--; + } + if (timeout == 0) + { + return RET_TIMEOUT; + } + + exmc_sdram_command_config(&sdram_command_init_struct); + + delay_1ms(10); + + 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_2_SDCLK; + sdram_command_init_struct.mode_register_content = 0; + + timeout = SDRAM_TIMEOUT; + while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) + { + timeout--; + } + if (timeout == 0) + { + return RET_TIMEOUT; + } + + exmc_sdram_command_config(&sdram_command_init_struct); + + 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_9_SDCLK; + sdram_command_init_struct.mode_register_content = 0; + + timeout = SDRAM_TIMEOUT; + while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) + { + timeout--; + } + if (timeout == 0) + { + return RET_TIMEOUT; + } + + exmc_sdram_command_config(&sdram_command_init_struct); + + 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_2_SDCLK; + sdram_command_init_struct.mode_register_content = command_content; + + timeout = SDRAM_TIMEOUT; + while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) + { + timeout--; + } + if (timeout == 0) + { + return RET_TIMEOUT; + } + + exmc_sdram_command_config(&sdram_command_init_struct); + + exmc_sdram_refresh_count_set(418); + + timeout = SDRAM_TIMEOUT; + while ((exmc_flag_get(exmc_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) + { + timeout--; + } + if (timeout == 0) + { + return RET_TIMEOUT; + } + + exmc_sdram_readsample_enable(ENABLE); + exmc_sdram_readsample_config(EXMC_SDRAM_4_DELAY_CELL, EXMC_SDRAM_READSAMPLE_0_EXTRAHCLK); + + return RET_OK; +} + RetCode SdramManager::init() { if (initialized_) @@ -42,49 +232,332 @@ RetCode SdramManager::init() } printf("[SdramManager] Initializing...\r\n"); - RetCode ret = sdram_init(&handle_); - if (ret == RET_OK) + + printf("[SDRAM] 开始初始化设备 %d\r\n", device_); + + switch (device_) { - initialized_ = true; - printf("[SdramManager] Init OK, base=0x%08lX\r\n", base_address()); + case DEVICE_0: + base_addr_ = SDRAM_DEVICE0_BASE_ADDR; + printf("[SDRAM] 使用设备0,基地址: 0x%08lX\r\n", base_addr_); + break; + case DEVICE_1: + base_addr_ = SDRAM_DEVICE1_BASE_ADDR; + printf("[SDRAM] 使用设备1,基地址: 0x%08lX\r\n", base_addr_); + break; + default: + printf("[SDRAM] 初始化失败: 无效设备 %d\r\n", device_); + return RET_INVALID_PARAM; } - else + + printf("[SDRAM] 配置信息:\r\n"); + printf(" 列地址宽度: %d\r\n", config_.column_address_width == EXMC_SDRAM_COW_ADDRESS_9 ? 9 : 8); + printf(" 行地址宽度: %d\r\n", config_.row_address_width == EXMC_SDRAM_ROW_ADDRESS_13 ? 13 : 12); + printf(" 数据宽度: %d位\r\n", config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B ? 16 : (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B ? 8 : 32)); + printf(" 内部Bank数: %d\r\n", config_.internal_bank_number == EXMC_SDRAM_4_INTER_BANK ? 4 : 2); + printf(" CAS延迟: %d个时钟\r\n", config_.cas_latency == EXMC_CAS_LATENCY_3_SDCLK ? 3 : 2); + printf(" 写保护: %s\r\n", config_.write_protection ? "启用" : "禁用"); + printf(" SDCLK配置: HCLK/%d\r\n", config_.sdclock_config == EXMC_SDCLK_PERIODS_3_HCLK ? 3 : 2); + + ExmcBus &exmc_bus = ExmcBus::instance(); + exmc_bus.init(); + ExmcBus::sdram_pin_init(); + printf("[SDRAM] EXMC总线初始化完成\r\n"); + + uint32_t exmc_device = getExmcDevice(); + uint32_t bank_select = getExmcBankSelect(); + printf("[SDRAM] EXMC设备: 0x%08lX, Bank选择: 0x%08lX\r\n", exmc_device, bank_select); + + printf("[SDRAM] 开始执行初始化序列...\r\n"); + RetCode ret = executeInitSequence(exmc_device, bank_select); + if (ret != RET_OK) { - printf("[SdramManager] Init failed: %d\r\n", ret); + printf("[SDRAM] 初始化序列失败: 错误码=%d\r\n", ret); + return ret; } - return ret; + + initialized_ = true; + + printf("[SDRAM] 初始化成功完成\r\n"); + printf("[SdramManager] Init OK, base=0x%08lX\r\n", base_addr_); + + return RET_OK; } RetCode SdramManager::write(uint32_t offset, const void *data, uint32_t length) { if (!initialized_) + { return RET_NOT_INITIALIZED; - return sdram_write(&handle_, offset, data, length); + } + + if (data == NULL || length == 0) + { + return RET_OK; + } + + uint32_t mem_addr = base_addr_ + offset; + + if (length > 1) + { + printf("[SDRAM] 写入: 地址=0x%08lX, 长度=%lu, 数据宽度=%d位\r\n", + mem_addr, length, + (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B) ? 8 : (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) ? 16 : 32); + if (length <= 16) + { + printf("[SDRAM] 数据: "); + const uint8_t *dbg_data = (const uint8_t *)data; + for (uint32_t i = 0; i < length && i < 16; i++) + { + printf("%02X ", dbg_data[i]); + } + printf("\r\n"); + } + } + + if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B) + { + uint8_t *dst = (uint8_t *)mem_addr; + const uint8_t *src = (const uint8_t *)data; + for (uint32_t i = 0; i < length; i++) + { + dst[i] = src[i]; + } + } + else if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) + { + volatile uint16_t *dst = (volatile uint16_t *)mem_addr; + const uint8_t *src = (const uint8_t *)data; + uint32_t halfword_len = length / 2; + for (uint32_t i = 0; i < halfword_len; i++) + { + dst[i] = (uint16_t)(src[i * 2] | ((uint16_t)src[i * 2 + 1] << 8)); + } + if (length & 1) + { + uint16_t last_word = dst[halfword_len]; + last_word = (last_word & 0xFF00) | src[length - 1]; + dst[halfword_len] = last_word; + } + __DSB(); + } + else if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_32B) + { + volatile uint32_t *dst = (volatile uint32_t *)mem_addr; + const uint32_t *src = (const uint32_t *)data; + uint32_t dword_len = length / 4; + for (uint32_t i = 0; i < dword_len; i++) + { + dst[i] = src[i]; + } + uint32_t remain = length % 4; + if (remain) + { + volatile uint8_t *dst8 = (volatile uint8_t *)&dst[dword_len]; + const uint8_t *src8 = (const uint8_t *)&src[dword_len]; + for (uint32_t i = 0; i < remain; i++) + { + dst8[i] = src8[i]; + } + } + } + else + { + return RET_NOT_SUPPORTED; + } + + __DSB(); + + return RET_OK; } RetCode SdramManager::read(uint32_t offset, void *buffer, uint32_t length) { if (!initialized_) + { return RET_NOT_INITIALIZED; - return sdram_read(&handle_, offset, buffer, length); + } + + if (buffer == NULL || length == 0) + { + return RET_OK; + } + + uint32_t mem_addr = base_addr_ + offset; + + if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B) + { + uint8_t *src = (uint8_t *)mem_addr; + uint8_t *dst = (uint8_t *)buffer; + for (uint32_t i = 0; i < length; i++) + { + dst[i] = src[i]; + } + } + else if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) + { + __DSB(); + volatile uint16_t *src = (volatile uint16_t *)mem_addr; + uint8_t *dst = (uint8_t *)buffer; + uint32_t halfword_len = length / 2; + for (uint32_t i = 0; i < halfword_len; i++) + { + uint32_t val = src[i]; + dst[i * 2] = (uint8_t)(val & 0xFF); + dst[i * 2 + 1] = (uint8_t)((val >> 8) & 0xFF); + } + if (length & 1) + { + uint16_t val = src[halfword_len]; + dst[length - 1] = (uint8_t)(val & 0xFF); + } + __DSB(); + } + else if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_32B) + { + volatile uint32_t *src = (volatile uint32_t *)mem_addr; + uint32_t *dst = (uint32_t *)buffer; + uint32_t dword_len = length / 4; + for (uint32_t i = 0; i < dword_len; i++) + { + dst[i] = src[i]; + } + uint32_t remain = length % 4; + if (remain) + { + volatile uint8_t *src8 = (volatile uint8_t *)&src[dword_len]; + uint8_t *dst8 = (uint8_t *)&dst[dword_len]; + for (uint32_t i = 0; i < remain; i++) + { + dst8[i] = src8[i]; + } + } + } + else + { + return RET_NOT_SUPPORTED; + } + + __DMB(); + + return RET_OK; } RetCode SdramManager::fill(uint32_t offset, uint8_t value, uint32_t length) { if (!initialized_) + { return RET_NOT_INITIALIZED; - return sdram_fill(&handle_, offset, value, length); + } + + if (length == 0) + { + return RET_OK; + } + + uint32_t mem_addr = base_addr_ + offset; + + if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_8B) + { + uint8_t *dst = (uint8_t *)mem_addr; + for (uint32_t i = 0; i < length; i++) + { + dst[i] = value; + } + } + else if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) + { + uint16_t word_value = (value << 8) | value; + uint8_t *dst8 = (uint8_t *)mem_addr; + uint16_t *dst16; + + if ((offset & 0x1) != 0) + { + dst8[0] = value; + dst8++; + length--; + } + + dst16 = (uint16_t *)dst8; + uint32_t word_count = length / 2; + for (uint32_t i = 0; i < word_count; i++) + { + dst16[i] = word_value; + } + + if (length & 0x1) + { + dst8 = (uint8_t *)&dst16[word_count]; + dst8[0] = value; + } + } + else if (config_.data_width == EXMC_SDRAM_DATABUS_WIDTH_32B) + { + uint32_t dword_value = (value << 24) | (value << 16) | (value << 8) | value; + uint32_t *dst = (uint32_t *)mem_addr; + uint32_t dword_count = (length + 3) / 4; + for (uint32_t i = 0; i < dword_count; i++) + { + dst[i] = dword_value; + } + } + else + { + return RET_NOT_SUPPORTED; + } + + return RET_OK; } RetCode SdramManager::self_test(uint32_t test_size) { if (!initialized_) + { return RET_NOT_INITIALIZED; - printf("[SdramManager] Running self-test (%lu bytes)...\r\n", test_size); - return sdram_self_test(&handle_, test_size); -} + } -uint32_t SdramManager::base_address() const -{ - return sdram_get_base_address(handle_.device); + printf("[SdramManager] Running self-test (%lu bytes)...\r\n", test_size); + + if (test_size > 1024 * 1024) + { + test_size = 1024 * 1024; + } + +#define SELF_TEST_BLOCK_SIZE 256 + + RetCode ret; + uint8_t write_buf[SELF_TEST_BLOCK_SIZE]; + uint8_t read_buf[SELF_TEST_BLOCK_SIZE]; + + for (uint32_t offset = 0; offset < test_size; offset += SELF_TEST_BLOCK_SIZE) + { + uint32_t block_size = (test_size - offset) > SELF_TEST_BLOCK_SIZE ? SELF_TEST_BLOCK_SIZE : (test_size - offset); + + for (uint32_t i = 0; i < block_size; i++) + { + write_buf[i] = (uint8_t)((offset + i) & 0xFF); + } + + ret = write(offset, write_buf, block_size); + if (ret != RET_OK) + { + return ret; + } + + ret = read(offset, read_buf, block_size); + if (ret != RET_OK) + { + return ret; + } + + for (uint32_t i = 0; i < block_size; i++) + { + if (read_buf[i] != write_buf[i]) + { + return RET_ERROR; + } + } + } + + return RET_OK; } diff --git a/bsp/device/sdram/sdram_manager.h b/bsp/device/sdram/sdram_manager.h index 7452f20..1481892 100644 --- a/bsp/device/sdram/sdram_manager.h +++ b/bsp/device/sdram/sdram_manager.h @@ -3,7 +3,6 @@ #include #include "common_types.h" -#include "sdram_driver.h" class SdramManager { public: @@ -24,8 +23,39 @@ private: SdramManager(const SdramManager &) = delete; SdramManager &operator=(const SdramManager &) = delete; - sdram_handle_t handle_; - bool initialized_ = false; + enum Device : uint8_t { DEVICE_0 = 0, DEVICE_1 = 1 }; + + struct Timing { + uint32_t load_mode_register_delay; + uint32_t exit_selfrefresh_delay; + uint32_t row_address_select_delay; + uint32_t auto_refresh_delay; + uint32_t write_recovery_delay; + uint32_t row_precharge_delay; + uint32_t row_to_column_delay; + }; + + struct Config { + uint32_t column_address_width; + uint32_t row_address_width; + uint32_t data_width; + uint32_t internal_bank_number; + uint32_t cas_latency; + bool write_protection; + uint32_t sdclock_config; + bool burst_read_switch; + uint32_t pipeline_read_delay; + Timing timing; + }; + + uint32_t getExmcDevice() const; + uint32_t getExmcBankSelect() const; + RetCode executeInitSequence(uint32_t exmc_device, uint32_t bank_select); + + Device device_{DEVICE_0}; + Config config_; + uint32_t base_addr_; + bool initialized_{false}; }; #endif