Initial commit: LSPi (LiangShanPi) project

GD32F470ZGT6 based project with full peripheral support:
- SDRAM (W9825G6KH) via EXMC
- LCD NT35510 (480x800) via EXMC NOR/PSRAM
- Flash (W25Q64) via SPI
- UART (USART0) debug console
- LED indicators
- CMSIS-DAP debug interface
- CMake + ARM GCC toolchain build system
This commit is contained in:
2026-04-26 16:24:42 +08:00
commit fc10ef2e10
152 changed files with 161765 additions and 0 deletions
+605
View File
@@ -0,0 +1,605 @@
#include "gd32f4xx.h"
#include "gd32f4xx_exmc.h"
#include "hardware_init.h"
#include "led_driver.h"
#include "uart_driver.h"
#include "systick.h"
#include "sdram_manager.h"
#include "flash_manager.h"
#include "lcd.h"
#include <cstdio>
#include <cstring>
/* SDRAM 中分配的测试变量 */
__attribute__((section(".sdram"))) uint8_t sdram_big_buffer[1024 * 1024];
/*
* 增量恢复版本
*
* STEP 控制当前启用的功能:
* STEP 0: LED 闪烁 + 直接 UART 输出(16MHz 下验证基础功能)
* STEP 1: + hardware_init(配到 168MHz
* STEP 2: + LedManager
* STEP 3: + UartBusC++ 驱动 + printf
* STEP 4: + SysTick(精确延时)
* STEP 5: + SDRAM / Flash / LCD 测试
*
* 每步都有 LED 模式指示状态。
* 修改 STEP 值来逐步启用功能
*/
#define STEP 5
#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
/* ---- 16MHz 延时 (ms*4000 ≈ 1ms) ---- */
static void delay_16m(uint32_t ms)
{
for (volatile uint32_t i = 0; i < ms * 4000U; i++)
;
}
/* ---- 直接 LED 控制 ---- */
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);
}
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);
}
/* ---- 直接 UART 控制 (USART0, PA9/PA10, 9600) ---- */
static void init_usart0(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_USART0);
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9 | GPIO_PIN_10);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9 | GPIO_PIN_10);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
usart_deinit(USART0);
usart_baudrate_set(USART0, 9600U);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
}
static void uart_putchar(char c)
{
usart_data_transmit(USART0, (uint8_t)c);
while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
;
}
static void uart_puts(const char *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]);
}
/* ---- 测试函数 ---- */
static void test_sdram_driver(void)
{
printf("SDRAM 驱动测试开始...\r\n");
SdramManager &sdram = SdramManager::instance();
RetCode ret = sdram.init();
if (ret != RET_OK)
{
printf(" SDRAM 初始化失败: 错误码=%d\r\n", ret);
return;
}
/* ---- 诊断测试1: 直接16位指针访问 ---- */
printf(" 诊断1: 直接16位指针读写...\r\n");
volatile uint16_t *sram16 = (volatile uint16_t *)0xC0000000;
for (uint32_t i = 0; i < 8; i++)
{
sram16[i] = (uint16_t)(0xAA00 + i);
}
__DSB();
delay_1ms(1);
bool diag1_ok = true;
for (uint32_t i = 0; i < 8; i++)
{
uint16_t val = sram16[i];
uint16_t expected = (uint16_t)(0xAA00 + i);
if (val != expected)
{
printf(" 16位错误 @ [%lu]: 期望=0x%04X, 读取=0x%04X\r\n", i, expected, val);
diag1_ok = false;
}
}
printf(" 诊断1: %s\r\n", diag1_ok ? "通过" : "失败");
/* ---- 诊断测试2: 直接32位指针访问(非零值) ---- */
printf(" 诊断2: 直接32位指针非零值测试...\r\n");
volatile uint32_t *sram32 = (volatile uint32_t *)0xC0000000;
sram32[0] = 0xDEADBEEF;
sram32[1] = 0xCAFEBABE;
sram32[2] = 0x12345678;
sram32[3] = 0x87654321;
__DSB();
delay_1ms(1);
bool diag2_ok = true;
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)
{
printf(" 32位错误 @ [%lu]: 期望=0x%08lX, 读取=0x%08lX\r\n", i, expected, val);
diag2_ok = false;
}
}
printf(" 诊断2: %s\r\n", diag2_ok ? "通过" : "失败");
/* ---- 诊断测试3: 通过驱动接口写/读 ---- */
printf(" 诊断3: 驱动接口读写...\r\n");
uint32_t write_val = 0xA5A55A5A;
uint32_t read_val = 0;
ret = sdram.write(64, &write_val, sizeof(write_val));
if (ret != RET_OK)
{
printf(" 驱动写入失败: %d\r\n", ret);
}
else
{
__DSB();
ret = sdram.read(64, &read_val, sizeof(read_val));
if (ret != RET_OK)
{
printf(" 驱动读取失败: %d\r\n", ret);
}
else
{
printf(" 写入=0x%08lX, 读取=0x%08lX, %s\r\n",
write_val, read_val,
(write_val == read_val) ? "通过" : "失败");
}
}
printf("SDRAM 驱动测试完成\r\n");
}
static void test_flash_driver(void)
{
printf("Flash 驱动测试开始...\r\n");
FlashManager &flash = FlashManager::instance();
RetCode ret = flash.init();
if (ret != RET_OK)
{
printf(" Flash 初始化失败: %d\r\n", ret);
return;
}
printf(" Flash 信息: 总大小=%lu KB, 扇区大小=%lu KB\r\n",
flash.total_size() / 1024, flash.sector_size() / 1024);
uint32_t test_address = 0x08000000U +
flash.total_size() -
flash.sector_size();
printf(" 测试地址: 0x%08lX\r\n", test_address);
uint8_t write_buffer[256];
uint8_t read_buffer[256];
for (int i = 0; i < 256; i++)
write_buffer[i] = (uint8_t)((i + 0x80) & 0xFF);
printf(" 擦除 Flash 扇区...\r\n");
ret = flash.erase(test_address, flash.sector_size());
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;
}
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;
}
printf(" Flash 读取成功\r\n");
bool verify_ok = true;
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");
ret = flash.self_test(256);
if (ret == RET_OK)
printf(" Flash 自测试通过\r\n");
else
printf(" Flash 自测试失败: %d\r\n", ret);
printf("Flash 驱动测试完成\r\n");
}
/* 时钟切换后重新配置USART0波特率(168MHz下9600 */
static void reinit_usart0_168m(void)
{
usart_deinit(USART0);
usart_baudrate_set(USART0, 9600U);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
}
static void test_lcd(void)
{
printf("\r\n===== LCD 完整功能测试 =====\r\n");
printf("[Step 0] LCD_Init (SDRAM 保持活跃)...\r\n");
LCD_Init();
printf("[Step 0] LCD ID: %s\r\n", lcd_id);
delay_1ms(500);
// ----- 4条水平色带: 每条200行, 全屏800行 -----
uint16_t bands[4] = {RED, GREEN, BLUE, WHITE};
for (int i = 0; i < 4; i++)
{
int y0 = i * 200;
int y1 = y0 + 199;
printf("[色带%d] y=%d~%d color=0x%04X\r\n", i, y0, y1, bands[i]);
BlockWrite(0, 479, y0, y1);
LCD_WriteRAM_Prepare();
for (int p = 0; p < 480 * 200; p++)
LCD_WriteRAM(bands[i]);
__DSB();
}
delay_1ms(3000);
// 全屏黑色清除
printf("[测试] LCD_Clear(BLACK)\r\n");
LCD_Clear(BLACK);
delay_1ms(1000);
// 全屏红色
printf("[测试] LCD_Clear(RED)\r\n");
LCD_Clear(RED);
delay_1ms(1000);
printf("LCD 测试完成!\r\n");
delay_1ms(2000);
}
static void test_sdram_after_lcd(void)
{
printf("\r\n===== SDRAM 数据保持验证 (LCD 操作后) =====\r\n");
volatile uint16_t *sram16 = (volatile uint16_t *)0xC0000000;
bool ok = true;
for (uint32_t i = 0; i < 8; i++)
{
uint16_t val = sram16[i];
uint16_t expected = (uint16_t)(0xAA00 + i);
if (val != expected)
{
printf(" SDRAM 数据错误 @ [%lu]: 期望=0x%04X, 读取=0x%04X\r\n", i, expected, val);
ok = false;
}
}
printf(" SDRAM 数据保持: %s\r\n", ok ? "通过 ? (LCD 未影响 SDRAM)" : "失败 ?");
volatile uint32_t *sram32 = (volatile uint32_t *)0xC0000000;
ok = true;
uint32_t expected_32[4] = {0xDEADBEEF, 0xCAFEBABE, 0x12345678, 0x87654321};
for (uint32_t i = 0; i < 4; i++)
{
uint32_t val = sram32[i];
if (val != expected_32[i])
{
printf(" SDRAM 32位数据错误 @ [%lu]: 期望=0x%08lX, 读取=0x%08lX\r\n", i, expected_32[i], val);
ok = false;
}
}
printf(" SDRAM 32位数据保持: %s\r\n", ok ? "通过 ?" : "失败 ?");
printf("SDRAM 验证完成\r\n");
}
static void concurrent_loop(void)
{
printf("\r\n===== 全部外设并发运行 =====\r\n");
printf("LED 闪烁 + UART 输出 + SDRAM 读写 + LCD 显示\r\n");
LCD_Clear(GREEN);
delay_1ms(500);
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);
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);
sram16[200 + iter] = (uint16_t)(iter * 0x2222);
__DSB();
val = sram16[200 + iter];
printf("[并发] iter=%d, SDRAM[%d]=0x%04X, LED2=ON\r\n", iter, 200 + iter, val);
delay_1ms(500);
counter += 2;
}
printf("\r\n===== 并发测试完成 =====\r\n");
printf("SDRAM 写入 %lu 个值, LCD 持续显示绿色\r\n", counter);
printf("所有外设 (Flash/SDRAM/LCD/UART/LED) 同时运行成功!\r\n");
LCD_Clear(BLUE);
delay_1ms(1000);
}
/* ============================================================== */
int main(void)
{
/* ============ STEP 0: 验证基础功能 ============ */
init_leds();
led_pattern(0x01);
init_usart0();
led_pattern(0x03);
uart_puts("\r\n===== STEP 0: Basic Functions =====\r\n");
uart_puts("LED + UART at 16MHz working\r\n");
uint32_t cs = RCU_CFG0 & RCU_CFG0_SCS;
uart_puts("Clock: ");
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");
/* LED 闪烁验证 */
uart_puts("Blinking LED2 3 times...\r\n");
for (int i = 0; i < 3; i++)
{
led_on(LED2_PORT, LED2_PIN);
delay_16m(200);
led_off(LED2_PORT, LED2_PIN);
delay_16m(200);
}
uart_puts("Blink OK\r\n");
led_pattern(0x03);
#if STEP >= 1
/* ============ STEP 1: hardware_init ============ */
uart_puts("\r\n===== STEP 1: hardware_init() =====\r\n");
led_pattern(0x04);
ret_code_t hw_ret = hardware_init();
/* 时钟已切换到168MHz,重新配置UART波特率 */
reinit_usart0_168m();
uart_puts("Return code: ");
uart_putdec((uint32_t)hw_ret);
uart_puts("\r\n");
cs = RCU_CFG0 & RCU_CFG0_SCS;
uart_puts("Clock after: ");
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");
led_pattern(0x05);
delay_16m(500);
#endif
#if STEP >= 2
/* ============ STEP 2: LedManager ============ */
uart_puts("\r\n===== STEP 2: LedManager =====\r\n");
led_pattern(0x06);
LedManager::instance().init_all();
LedManager::instance().led(1).on();
delay_16m(200);
LedManager::instance().led(1).off();
uart_puts("LedManager OK\r\n");
led_pattern(0x07);
#endif
#if STEP >= 3
/* ============ STEP 3: UartBus ============ */
uart_puts("\r\n===== STEP 3: UartBus =====\r\n");
led_pattern(0x08);
{
UartConfig cfg;
cfg.baudrate = 9600;
UartBus::default_instance().init(cfg);
}
uart_puts("UartBus init OK\r\n");
led_pattern(0x09);
#endif
#if STEP >= 4
/* ============ STEP 4: SysTick ============ */
uart_puts("\r\n===== STEP 4: SysTick =====\r\n");
led_pattern(0x0A);
systick_config();
uart_puts("systick_config() OK\r\n");
delay_1ms(500);
uart_puts("delay_1ms(500) OK\r\n");
led_pattern(0x0B);
#endif
#if STEP >= 5
/* ============ STEP 5: Full tests ============ */
uart_puts("\r\n===== STEP 5: 全部外设测试 =====\r\n");
led_pattern(0x0C);
/* SDRAM 测试 */
test_sdram_driver();
delay_1ms(500);
/* Flash 测试 */
test_flash_driver();
delay_1ms(500);
/* LCD 测试 (SDRAM 保持活跃, 不移除 SDRAM 初始化) */
test_lcd();
delay_1ms(500);
/* 验证 SDRAM 数据在 LCD 操作后仍然保持 */
test_sdram_after_lcd();
delay_1ms(500);
/* 全部外设并发运行: SDRAM + LCD + Flash + UART + LED */
concurrent_loop();
delay_1ms(500);
led_pattern(0x0D);
#endif
/* ============ 主循环 ============ */
uart_puts("\r\n===== Main Loop =====\r\n");
uart_puts("All hardware tests passed! System running at 168MHz\r\n");
led_pattern(0x0F);
uint32_t tick = 0;
while (1)
{
led_on(LED4_PORT, LED4_PIN);
delay_1ms(250);
led_off(LED4_PORT, LED4_PIN);
delay_1ms(250);
tick++;
if (tick % 4 == 0)
{
printf(".");
}
}
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef __MAIN_H__
#define __MAIN_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#ifdef __cplusplus
}
#endif
#endif
+209
View File
@@ -0,0 +1,209 @@
#include "gd32f4xx.h"
#include "systick.h"
#include "lcd.h"
#include "../../libs/thirdparty/GD32F4xx_Official/LCD_TOUCH_MCU_LiangShanPi/Hardware/usart0/usart0.h"
#include <stdio.h>
// LED引脚定义 - 梁山Pi开发板使用PD7作为LED1
#define LED_PORT GPIOD
#define LED_PIN GPIO_PIN_7
// 简单软件延时函数(不使用SysTick)
static void software_delay_ms(uint32_t ms)
{
// 基于16MHz时钟的粗略延时
for(volatile uint32_t i = 0; i < ms * 8000; i++);
}
// LED闪烁函数,用于指示当前测试阶段
static void led_blink_pattern(uint8_t pattern, uint16_t delay_ms)
{
switch(pattern) {
case 0:
// 模式0:快速闪烁3次(测试开始)
for(int i = 0; i < 3; i++) {
gpio_bit_set(LED_PORT, LED_PIN);
software_delay_ms(100);
gpio_bit_reset(LED_PORT, LED_PIN);
software_delay_ms(100);
}
break;
case 1:
// 模式1:闪烁1次(步骤1完成)
gpio_bit_set(LED_PORT, LED_PIN);
software_delay_ms(500);
gpio_bit_reset(LED_PORT, LED_PIN);
software_delay_ms(500);
break;
case 2:
// 模式2:闪烁2次(步骤2完成)
for(int i = 0; i < 2; i++) {
gpio_bit_set(LED_PORT, LED_PIN);
software_delay_ms(300);
gpio_bit_reset(LED_PORT, LED_PIN);
software_delay_ms(300);
}
break;
case 3:
// 模式3:闪烁3次(步骤3完成)
for(int i = 0; i < 3; i++) {
gpio_bit_set(LED_PORT, LED_PIN);
software_delay_ms(200);
gpio_bit_reset(LED_PORT, LED_PIN);
software_delay_ms(200);
}
break;
case 4:
// 模式4:闪烁4次(步骤4完成)
for(int i = 0; i < 4; i++) {
gpio_bit_set(LED_PORT, LED_PIN);
software_delay_ms(150);
gpio_bit_reset(LED_PORT, LED_PIN);
software_delay_ms(150);
}
break;
}
// 阶段间延时
software_delay_ms(delay_ms);
}
int main(void)
{
// 启用GPIOD时钟
rcu_periph_clock_enable(RCU_GPIOD);
// 初始化串口调试输出(USART0, PA9/PA10, 9600 baud
usart0_init();
// 简单串口测试:直接发送字符,不使用printf
// 发送测试字符串 "UART TEST"
const char test_str[] = "UART TEST\r\n";
for(int i = 0; i < sizeof(test_str)-1; i++) {
usart_data_transmit(USART0, (uint8_t)test_str[i]);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
// 添加延时确保串口稳定
for(volatile uint32_t i = 0; i < 100000; i++);
printf("\r\n\r\n=== LCD初始化分步测试程序 ===\r\n");
printf("系统时钟: 16MHz IRC16M\r\n");
printf("串口波特率: 9600\r\n");
printf("开始测试...\r\n");
// 配置PD7为推挽输出
gpio_mode_set(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN);
gpio_output_options_set(LED_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED_PIN);
// 初始状态:LED灭
gpio_bit_reset(LED_PORT, LED_PIN);
// ===== 阶段0:系统基本功能测试 =====
printf("[阶段0] 系统基本功能测试...\r\n");
// 快速闪烁3次确认系统正常运行
led_blink_pattern(0, 1000);
// ===== 阶段1:配置SysTick =====
printf("[阶段1] 配置SysTick定时器...\r\n");
systick_config();
// 等待500ms让SysTick稳定
delay_1ms(500);
// 闪烁1次指示SysTick配置完成
gpio_bit_set(LED_PORT, LED_PIN);
delay_1ms(200);
gpio_bit_reset(LED_PORT, LED_PIN);
delay_1ms(200);
gpio_bit_set(LED_PORT, LED_PIN);
delay_1ms(200);
gpio_bit_reset(LED_PORT, LED_PIN);
delay_1ms(1000);
printf("[阶段1] SysTick配置成功!\r\n");
// ===== 阶段2LCD GPIO配置测试 =====
printf("[阶段2] 开始LCD GPIO配置测试...\r\n");
// 调用LCD_CtrlLinesConfig() - GPIO配置
led_blink_pattern(1, 500); // 闪烁1次,即将开始步骤1
// 执行LCD GPIO配置
printf("[阶段2] 正在配置LCD GPIO引脚...\r\n");
LCD_CtrlLinesConfig();
// 如果程序执行到这里,说明LCD_CtrlLinesConfig()没有卡住
printf("[阶段2] LCD GPIO配置成功!\r\n");
led_blink_pattern(2, 1000); // 闪烁2次,步骤1完成
// ===== 阶段3LCD FSMC配置测试 =====
printf("[阶段3] 开始LCD FSMC配置测试...\r\n");
// 调用LCD_FSMCConfig() - FSMC配置
led_blink_pattern(2, 500); // 闪烁2次,即将开始步骤2
// 执行LCD FSMC配置
printf("[阶段3] 正在配置FSMC控制器...\r\n");
LCD_FSMCConfig();
// 如果程序执行到这里,说明LCD_FSMCConfig()没有卡住
printf("[阶段3] LCD FSMC配置成功!\r\n");
led_blink_pattern(3, 1000); // 闪烁3次,步骤2完成
// ===== 阶段4LCD ID读取测试 =====
printf("[阶段4] 开始LCD ID读取测试...\r\n");
// 调用LcdNT35510ReadID() - 读取LCD ID
led_blink_pattern(3, 500); // 闪烁3次,即将开始步骤3
// 执行LCD ID读取
printf("[阶段4] 正在读取LCD ID...\r\n");
LcdNT35510ReadID();
// 如果程序执行到这里,说明LcdNT35510ReadID()没有卡住
printf("[阶段4] LCD ID读取成功!\r\n");
led_blink_pattern(4, 1000); // 闪烁4次,步骤3完成
// ===== 阶段5LCD参数配置测试 =====
printf("[阶段5] 开始LCD参数配置测试...\r\n");
// 调用LCD_HVGA_NT35510() - LCD参数配置
led_blink_pattern(4, 500); // 闪烁4次,即将开始步骤4
// 执行LCD参数配置
printf("[阶段5] 正在配置LCD参数...\r\n");
LCD_HVGA_NT35510();
// 如果程序执行到这里,说明LCD_HVGA_NT35510()没有卡住
printf("[阶段5] LCD参数配置成功!\r\n");
// 长亮3秒指示成功
gpio_bit_set(LED_PORT, LED_PIN);
delay_1ms(3000);
gpio_bit_reset(LED_PORT, LED_PIN);
delay_1ms(1000);
// ===== 阶段6LCD初始化代码测试 =====
printf("[阶段6] 开始LCD初始化序列测试...\r\n");
// 调用NT35510_HY35_Initial_Code() - LCD初始化序列
// 快速闪烁5次指示即将开始LCD初始化
for(int i = 0; i < 5; i++) {
gpio_bit_set(LED_PORT, LED_PIN);
delay_1ms(100);
gpio_bit_reset(LED_PORT, LED_PIN);
delay_1ms(100);
}
delay_1ms(1000);
// 执行LCD初始化序列
printf("[阶段6] 正在执行LCD初始化序列...\r\n");
NT35510_HY35_Initial_Code();
// 如果程序执行到这里,说明整个LCD初始化成功!
printf("[阶段6] LCD初始化序列成功!整个LCD初始化完成!\r\n");
// 最终成功指示:LED持续快速闪烁
while(1) {
gpio_bit_set(LED_PORT, LED_PIN);
delay_1ms(100);
gpio_bit_reset(LED_PORT, LED_PIN);
delay_1ms(100);
}
}
+792
View File
@@ -0,0 +1,792 @@
#include "gd32f4xx.h"
#include "systick.h"
#include "lcd.h"
#include "../bsp/device/led/led_driver.h"
#include "../drv/uart/uart_driver.h"
#include "../bsp/device/sdram/sdram_driver.h"
#include "../bsp/device/flash/flash_driver.h"
#include "../bsp/hardware_init.h"
#include <cstdio>
#include <cstring>
extern _lcd_dev lcddev;
__attribute__((section(".sdram"))) uint8_t sdram_framebuffer[800 * 480 * 3];
__attribute__((section(".sdram"))) uint16_t sdram_audio_buffer[65536];
__attribute__((section(".sdram"))) uint8_t sdram_big_buffer[1024 * 1024];
__attribute__((section(".sdram"))) struct
{
uint32_t header;
uint8_t data[1024 * 64];
} sdram_packet_pool;
static void uart_send_string(const char *str)
{
while (*str)
{
fputc(*str, stdout);
str++;
}
}
static void software_delay_ms(uint32_t ms)
{
for (volatile uint32_t i = 0; i < ms * 8000; i++)
;
}
static void demo_sdram_variable_usage(void)
{
printf("\r\n");
printf("========================================\r\n");
printf(" SDRAM 变量直接访问演示 (像内置RAM一样)\r\n");
printf("========================================\r\n");
printf("[演示1] 像普通数组一样直接赋值和读取:\r\n");
sdram_big_buffer[0] = 0x12;
sdram_big_buffer[1] = 0x34;
sdram_big_buffer[2] = 0x56;
sdram_big_buffer[3] = 0x78;
printf(" sdram_big_buffer[0..3] = 0x%02X 0x%02X 0x%02X 0x%02X\r\n",
sdram_big_buffer[0], sdram_big_buffer[1],
sdram_big_buffer[2], sdram_big_buffer[3]);
printf("[演示2] 使用memset/memcpy标准库函数:\r\n");
memset(sdram_framebuffer, 0x00, sizeof(sdram_framebuffer));
sdram_framebuffer[0] = 0xFF;
sdram_framebuffer[799] = 0xAA;
printf(" 帧缓冲首字节=0x%02X 末字节=0x%02X (总大小=%lu 字节)\r\n",
sdram_framebuffer[0], sdram_framebuffer[799],
(unsigned long)sizeof(sdram_framebuffer));
printf("[演示3] 结构体操作:\r\n");
sdram_packet_pool.header = 0xA5A5A5A5;
for (int i = 0; i < 5; i++)
sdram_packet_pool.data[i] = 0x10 + i;
printf(" header=0x%08lX data[0..4]=0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\r\n",
sdram_packet_pool.header,
sdram_packet_pool.data[0], sdram_packet_pool.data[1],
sdram_packet_pool.data[2], sdram_packet_pool.data[3],
sdram_packet_pool.data[4]);
printf("[演示4] 通过不同类型指针读写:\r\n");
uint32_t *ptr32 = (uint32_t *)&sdram_big_buffer[0];
ptr32[0] = 0xDEADBEEF;
ptr32[1] = 0xCAFEBABE;
printf(" 以 uint32_t 指针写入后: [0]=0x%08lX [1]=0x%08lX\r\n",
ptr32[0], ptr32[1]);
printf("[演示5] 地址验证 (变量是否在SDRAM地址范围 0xC0000000+):\r\n");
printf(" sdram_framebuffer = 0x%08lX\r\n", (unsigned long)sdram_framebuffer);
printf(" sdram_audio_buffer = 0x%08lX\r\n", (unsigned long)sdram_audio_buffer);
printf(" sdram_big_buffer = 0x%08lX\r\n", (unsigned long)sdram_big_buffer);
printf(" sdram_packet_pool = 0x%08lX\r\n", (unsigned long)&sdram_packet_pool);
printf(" 所有变量地址均在 SDRAM 范围内 √\r\n");
printf("[演示6] 与驱动API读写同一地址,数据一致:\r\n");
sdram_big_buffer[100] = 0x7F;
printf(" 直接赋值: sdram_big_buffer[100] = 0x%02X\r\n", sdram_big_buffer[100]);
printf("========================================\r\n");
printf(" 总结: 像内置RAM一样声明和使用SDRAM变量√\r\n");
printf(" 用法: __attribute__((section(\".sdram\"))) 类型 变量名;\r\n");
printf("========================================\r\n");
printf("\r\n");
}
static void test_sdram_driver(void)
{
printf("SDRAM驱动测试开始...\r\n");
printf("SDRAM型号: W9825G6KH-6I (32Mx16位, 64MB, CAS延迟6)\r\n");
printf("注意: GD32 EXMC控制器支持CAS延迟2或3,使用CAS延迟3进行测试\r\n");
sdram_handle_t sdram_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 = false,
.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,
}},
.private_data = NULL};
ret_code_t ret = sdram_init(&sdram_handle);
if (ret != RET_OK)
{
printf(" SDRAM初始化失败: 错误码=%d\r\n", ret);
if (ret == RET_TIMEOUT)
{
printf(" 错误类型: 初始化超时\r\n");
}
return;
}
printf(" SDRAM初始化成功\r\n");
printf(" SDRAM配置: 数据宽度=%d位, CAS延迟=%d, 时钟分频=HCLK/%d\r\n",
(sdram_handle.config.data_width == EXMC_SDRAM_DATABUS_WIDTH_16B) ? 16 : (sdram_handle.config.data_width == EXMC_SDRAM_DATABUS_WIDTH_32B) ? 32
: 8,
(sdram_handle.config.cas_latency == EXMC_CAS_LATENCY_3_SDCLK) ? 3 : (sdram_handle.config.cas_latency == EXMC_CAS_LATENCY_2_SDCLK) ? 2
: 1,
(sdram_handle.config.sdclock_config == EXMC_SDCLK_PERIODS_3_HCLK) ? 3 : 2);
printf(" 开始SDRAM读写测试...\r\n");
uint8_t write_buffer[256];
uint8_t read_buffer[256];
uint8_t zero_buffer[256];
uint8_t ff_buffer[256];
for (int i = 0; i < 256; i++)
{
write_buffer[i] = (uint8_t)(i & 0xFF);
}
memset(zero_buffer, 0x00, sizeof(zero_buffer));
memset(ff_buffer, 0xFF, sizeof(ff_buffer));
printf(" 测试数据生成完成,前16字节: ");
for (int i = 0; i < 16 && i < sizeof(write_buffer); i++)
{
printf("%02X ", write_buffer[i]);
}
printf("\r\n");
printf(" 步骤1: 测试地址0x00000000的单字节访问...\r\n");
uint8_t test_byte = 0x55;
uint8_t verify_byte;
ret = sdram_write(&sdram_handle, 0, &test_byte, 1);
if (ret != RET_OK)
{
printf(" 地址0x00000000单字节写入失败: 错误码=%d\r\n", ret);
}
else
{
ret = sdram_read(&sdram_handle, 0, &verify_byte, 1);
if (ret != RET_OK)
{
printf(" 地址0x00000000单字节读取失败: 错误码=%d\r\n", ret);
}
else
{
printf(" 地址0x00000000单字节测试: 写入=0x%02X, 读取=0x%02X %s\r\n",
test_byte, verify_byte, (verify_byte == test_byte) ? "(成功)" : "(失败)");
}
}
printf(" 步骤2: 写入256字节到SDRAM地址 0x1000...\r\n");
ret = sdram_write(&sdram_handle, 0x1000, write_buffer, sizeof(write_buffer));
if (ret != RET_OK)
{
printf(" SDRAM写入失败: 错误码=%d\r\n", ret);
if (ret == RET_NOT_INITIALIZED)
printf(" 错误类型: SDRAM未初始化\r\n");
else if (ret == RET_INVALID_PARAM)
printf(" 错误类型: 无效参数\r\n");
else if (ret == RET_TIMEOUT)
printf(" 错误类型: 操作超时\r\n");
sdram_deinit(&sdram_handle);
return;
}
printf(" SDRAM写入成功\r\n");
printf(" 步骤3: 从SDRAM地址 0x1000 读取256字节...\r\n");
ret = sdram_read(&sdram_handle, 0x1000, read_buffer, sizeof(read_buffer));
if (ret != RET_OK)
{
printf(" SDRAM读取失败: 错误码=%d\r\n", ret);
sdram_deinit(&sdram_handle);
return;
}
printf(" SDRAM读取成功\r\n");
printf(" 读取到的前16字节: ");
for (int i = 0; i < 16 && i < sizeof(read_buffer); i++)
{
printf("%02X ", read_buffer[i]);
}
printf("\r\n");
printf(" 步骤4: 数据验证...\r\n");
bool verify_ok = true;
int first_error_index = -1;
uint8_t expected_value = 0, actual_value = 0;
for (int i = 0; i < 256; i++)
{
if (read_buffer[i] != write_buffer[i])
{
verify_ok = false;
first_error_index = i;
expected_value = write_buffer[i];
actual_value = read_buffer[i];
break;
}
}
if (!verify_ok)
{
printf(" 数据验证失败 @ 索引 %d: 期望=0x%02X, 实际=0x%02X\r\n",
first_error_index, expected_value, actual_value);
bool all_zero = true;
bool all_ff = true;
for (int i = 0; i < 256; i++)
{
if (read_buffer[i] != 0x00)
all_zero = false;
if (read_buffer[i] != 0xFF)
all_ff = false;
if (!all_zero && !all_ff)
break;
}
if (all_zero)
{
printf(" 警告: 读取到的数据全为0x00 (可能写入未生效)\r\n");
}
else if (all_ff)
{
printf(" 警告: 读取到的数据全为0xFF (可能SDRAM未初始化或访问失败)\r\n");
}
printf(" 错误位置附近数据 (索引 %d-%d):\r\n",
(first_error_index > 8) ? first_error_index - 8 : 0,
(first_error_index < 248) ? first_error_index + 8 : 255);
printf(" 索引: ");
for (int i = (first_error_index > 8) ? first_error_index - 8 : 0;
i <= ((first_error_index < 248) ? first_error_index + 8 : 255); i++)
{
printf("%3d ", i);
}
printf("\r\n");
printf(" 期望: ");
for (int i = (first_error_index > 8) ? first_error_index - 8 : 0;
i <= ((first_error_index < 248) ? first_error_index + 8 : 255); i++)
{
printf("%02X ", write_buffer[i]);
}
printf("\r\n");
printf(" 实际: ");
for (int i = (first_error_index > 8) ? first_error_index - 8 : 0;
i <= ((first_error_index < 248) ? first_error_index + 8 : 255); i++)
{
printf("%02X ", read_buffer[i]);
}
printf("\r\n");
}
else
{
printf(" SDRAM数据验证成功 (所有256字节匹配)\r\n");
}
printf(" 步骤5: 执行SDRAM自测试 (1KB范围)...\r\n");
ret = sdram_self_test(&sdram_handle, 1024);
if (ret == RET_OK)
{
printf(" SDRAM自测试通过\r\n");
}
else
{
printf(" SDRAM自测试失败: 错误码=%d\r\n", ret);
}
printf(" 步骤6: 测试不同地址 (0x2000)...\r\n");
uint8_t test_value = 0xAA;
uint8_t verify_value;
ret = sdram_write(&sdram_handle, 0x2000, &test_value, 1);
if (ret == RET_OK)
{
ret = sdram_read(&sdram_handle, 0x2000, &verify_value, 1);
if (ret == RET_OK)
{
if (verify_value == test_value)
{
printf(" 地址0x2000测试通过: 写入=0x%02X, 读取=0x%02X\r\n", test_value, verify_value);
}
else
{
printf(" 地址0x2000测试失败: 写入=0x%02X, 读取=0x%02X\r\n", test_value, verify_value);
}
}
else
{
printf(" 地址0x2000读取失败: %d\r\n", ret);
}
}
else
{
printf(" 地址0x2000写入失败: %d\r\n", ret);
}
demo_sdram_variable_usage();
printf(" 反初始化SDRAM...\r\n");
sdram_deinit(&sdram_handle);
printf("SDRAM驱动测试完成\r\n");
}
static void test_flash_driver(void)
{
printf("Flash驱动测试开始...\r\n");
flash_handle_t flash_handle = {
.type = FLASH_TYPE_INTERNAL,
.config = {
.type = FLASH_TYPE_INTERNAL,
.base_address = flash_get_internal_base_address(),
.clock_freq = 0,
.cs_pin = 0,
.spi_port = 0,
.exmc_bank = 0},
.info = {.total_size = flash_get_internal_total_size(), .sector_size = flash_get_internal_sector_size(), .page_size = 256, .block_size = 64 * 1024, .manufacturer_id = 0x20, .device_id = 0x470},
.initialized = false,
.private_data = NULL};
ret_code_t ret = flash_init(&flash_handle);
if (ret != RET_OK)
{
printf(" Flash初始化失败: %d\r\n", ret);
return;
}
printf(" Flash初始化成功\r\n");
flash_info_t flash_info;
ret = flash_get_info(&flash_handle, &flash_info);
if (ret == RET_OK)
{
printf(" Flash信息: 总大小=%lu KB, 扇区大小=%lu KB\r\n",
flash_info.total_size / 1024, flash_info.sector_size / 1024);
}
uint32_t test_address = flash_get_internal_base_address() +
flash_get_internal_total_size() -
flash_get_internal_sector_size();
printf(" 测试地址: 0x%08lX\r\n", test_address);
uint8_t write_buffer[256];
uint8_t read_buffer[256];
for (int i = 0; i < 256; i++)
{
write_buffer[i] = (uint8_t)((i + 0x80) & 0xFF);
}
printf(" 擦除Flash扇区...\r\n");
printf(" 扇区地址: 0x%08lX, 扇区大小: %lu 字节\r\n",
test_address, flash_get_internal_sector_size());
ret = flash_erase(&flash_handle, test_address, flash_get_internal_sector_size());
if (ret != RET_OK)
{
printf(" Flash擦除失败: 错误码=%d\r\n", ret);
if (ret == RET_TIMEOUT)
{
printf(" 错误类型: 操作超时\r\n");
}
else if (ret == RET_ERROR)
{
printf(" 错误类型: Flash操作错误\r\n");
}
flash_deinit(&flash_handle);
return;
}
printf(" Flash擦除成功\r\n");
printf(" 写入Flash数据...\r\n");
ret = flash_write(&flash_handle, test_address, write_buffer, sizeof(write_buffer));
if (ret != RET_OK)
{
printf(" Flash写入失败: %d\r\n", ret);
flash_deinit(&flash_handle);
return;
}
printf(" Flash写入成功\r\n");
printf(" 读取Flash数据...\r\n");
ret = flash_read(&flash_handle, test_address, read_buffer, sizeof(read_buffer));
if (ret != RET_OK)
{
printf(" Flash读取失败: %d\r\n", ret);
flash_deinit(&flash_handle);
return;
}
printf(" Flash读取成功\r\n");
bool verify_ok = true;
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");
}
ret = flash_self_test(&flash_handle, 256);
if (ret == RET_OK)
{
printf(" Flash自测试通过\r\n");
}
else
{
printf(" Flash自测试失败: %d\r\n", ret);
}
flash_deinit(&flash_handle);
printf("Flash驱动测试完成\r\n");
}
static void test_external_spi_flash(void)
{
printf("外部SPI Flash驱动测试开始...\r\n");
ret_code_t ret = flash_external_spi_default_init();
if (ret != RET_OK)
{
printf(" 外部SPI Flash初始化失败: %d\r\n", ret);
return;
}
printf(" 外部SPI Flash初始化成功\r\n");
flash_handle_t *flash_handle = flash_get_external_spi_handle();
if (flash_handle == NULL)
{
printf(" 获取外部SPI Flash句柄失败\r\n");
return;
}
printf(" 制造商ID: 0x%02lX\r\n", flash_handle->info.manufacturer_id);
printf(" 设备ID: 0x%04lX\r\n", flash_handle->info.device_id);
printf(" 总容量: %lu KB\r\n", flash_handle->info.total_size / 1024);
printf(" 扇区大小: %lu KB\r\n", flash_handle->info.sector_size / 1024);
printf(" 页大小: %lu 字节\r\n", flash_handle->info.page_size);
uint8_t read_buffer[256];
ret = flash_read(flash_handle, 0, read_buffer, sizeof(read_buffer));
if (ret != RET_OK)
{
printf(" 读取测试失败: %d\r\n", ret);
}
else
{
printf(" 读取测试成功(读取前256字节)\r\n");
printf(" 前16字节内容: ");
for (int i = 0; i < 16 && i < sizeof(read_buffer); i++)
{
printf("%02X ", read_buffer[i]);
}
printf("\r\n");
}
printf("\r\n");
printf(" 开始完整功能测试(写入/擦除/验证)...\r\n");
uint32_t status;
ret = flash_read_status(flash_handle, &status);
if (ret == RET_OK)
{
printf(" 当前状态寄存器: 0x%02lX\r\n", status);
printf(" 状态位: BUSY=%d, WEL=%d, BP0=%d, BP1=%d, BP2=%d, BP3=%d, SRWD=%d\r\n",
(int)((status >> 0) & 1), (int)((status >> 1) & 1), (int)((status >> 2) & 1),
(int)((status >> 3) & 1), (int)((status >> 4) & 1), (int)((status >> 5) & 1),
(int)((status >> 7) & 1));
}
printf(" 选择测试扇区: 最后一个4KB扇区 (避免破坏现有数据)\r\n");
uint32_t test_sector = flash_handle->info.total_size - flash_handle->info.sector_size;
printf(" 测试地址: 0x%08lX\r\n", test_sector);
uint8_t sector_buffer[256];
ret = flash_read(flash_handle, test_sector, sector_buffer, sizeof(sector_buffer));
if (ret == RET_OK)
{
printf(" 测试扇区前16字节: ");
for (int i = 0; i < 16; i++)
printf("%02X ", sector_buffer[i]);
printf("\r\n");
}
printf(" 擦除测试扇区...\r\n");
ret = flash_erase(flash_handle, test_sector, flash_handle->info.sector_size);
if (ret != RET_OK)
{
printf(" 擦除失败: %d\r\n", ret);
flash_deinit(flash_handle);
return;
}
printf(" 擦除成功\r\n");
bool erase_ok = false;
uint8_t verify_erase_buf[16];
ret = flash_read(flash_handle, test_sector, verify_erase_buf, sizeof(verify_erase_buf));
if (ret == RET_OK)
{
erase_ok = true;
for (int i = 0; i < 16; i++)
{
if (verify_erase_buf[i] != 0xFF)
{
erase_ok = false;
break;
}
}
printf(" 擦除验证: %s\r\n", erase_ok ? "通过" : "失败");
}
uint8_t test_data[256];
for (int i = 0; i < 256; i++)
test_data[i] = (uint8_t)(i ^ 0x55);
printf(" 写入测试数据 (256字节, 模式: i ^ 0x55)...\r\n");
ret = flash_write(flash_handle, test_sector, test_data, sizeof(test_data));
if (ret != RET_OK)
{
printf(" 写入失败: %d\r\n", ret);
flash_deinit(flash_handle);
return;
}
printf(" 写入成功\r\n");
uint8_t verify_buf[256];
ret = flash_read(flash_handle, test_sector, verify_buf, sizeof(verify_buf));
if (ret != RET_OK)
{
printf(" 读取验证失败: %d\r\n", ret);
flash_deinit(flash_handle);
return;
}
bool write_verified = true;
for (int i = 0; i < 256; i++)
{
if (verify_buf[i] != test_data[i])
{
write_verified = false;
printf(" 数据不匹配 @ 字节 %d: 期望=0x%02X, 实际=0x%02X\r\n", i, test_data[i], verify_buf[i]);
if (i >= 10)
{
printf(" (显示前10个错误后停止)\r\n");
break;
}
}
}
if (write_verified)
{
printf(" 写入验证: 通过 (所有256字节匹配)\r\n");
}
printf(" 测试跨页写入 (256+128=384字节)...\r\n");
uint8_t cross_page_data[384];
for (int i = 0; i < 384; i++)
cross_page_data[i] = (uint8_t)(i & 0xFF);
ret = flash_write(flash_handle, test_sector + 256, cross_page_data, sizeof(cross_page_data));
if (ret == RET_OK)
{
printf(" 跨页写入成功\r\n");
}
else
{
printf(" 跨页写入失败: %d (此错误在某些Flash型号中可能正常)\r\n", ret);
}
printf("\r\n");
if (erase_ok && write_verified)
{
printf(" ? 外部SPI Flash完整功能测试通过!\r\n");
printf(" 擦除、写入、读取、验证所有功能正常。\r\n");
}
else
{
printf(" ?? 外部SPI Flash测试部分通过。\r\n");
printf(" 需要进一步检查问题。\r\n");
}
flash_deinit(flash_handle);
printf("外部SPI Flash驱动测试完成\r\n");
}
static const char *get_clock_source_str(void)
{
uint32_t scs = RCU_CFG0 & RCU_CFG0_SCS;
if (scs == RCU_SCSS_IRC16M)
{
return "IRC16M (内部16MHz)";
}
else if (scs == RCU_SCSS_HXTAL)
{
return "HXTAL (外部25MHz晶体)";
}
else if (scs == RCU_SCSS_PLLP)
{
return "PLL (168MHz)";
}
else
{
return "未知";
}
}
static const char *get_system_clock_str(void)
{
uint32_t scs = RCU_CFG0 & RCU_CFG0_SCS;
if (scs == RCU_SCSS_IRC16M)
{
return "16MHz";
}
else if (scs == RCU_SCSS_HXTAL)
{
return "25MHz";
}
else if (scs == RCU_SCSS_PLLP)
{
return "168MHz";
}
else
{
return "未知频率";
}
}
static void lcd_display_demo(void)
{
printf("LCD初始化...\r\n");
LCD_Init();
printf(" LCD ID: %s\r\n", lcd_id);
printf(" LCD分辨率: %dx%d\r\n", lcddev.width, lcddev.height);
printf(" Step 1: 逐步骤诊断测试 (含寄存器读回验证)...\r\n");
LCD_DiagnosticPattern();
printf(" [诊断完成, 等待 5 秒观察屏幕]...\r\n");
delay_1ms(5000);
printf(" Step 2: 全屏纯色测试开始\r\n");
printf(" 全屏 RED...\r\n");
LCD_Clear(RED);
delay_1ms(2000);
printf(" 全屏 GREEN...\r\n");
LCD_Clear(GREEN);
delay_1ms(2000);
printf(" 全屏 BLUE...\r\n");
LCD_Clear(BLUE);
delay_1ms(2000);
printf(" 全屏 WHITE...\r\n");
LCD_Clear(WHITE);
delay_1ms(2000);
POINT_COLOR = RED;
BACK_COLOR = WHITE;
LCD_ShowString(30, 40, 400, 32, 16, 0, (uint8_t *)"LiangShanPi GD32F470");
LCD_ShowString(30, 70, 400, 32, 16, 0, (uint8_t *)"LCD: NT35510 480x800");
POINT_COLOR = BLUE;
LCD_ShowString(30, 110, 400, 32, 16, 0, lcd_id);
LCD_ShowString(30, 150, 400, 32, 16, 0, (uint8_t *)"SDRAM + LCD Coexistence OK");
POINT_COLOR = BLACK;
LCD_ShowString(30, 200, 400, 32, 16, 0, (uint8_t *)"System: 168MHz");
LCD_ShowString(30, 240, 400, 32, 16, 0, (uint8_t *)"Hello World!");
POINT_COLOR = RED;
LCD_DrawRectangle(20, 300, 220, 500);
POINT_COLOR = GREEN;
LCD_FillRectangle(30, 310, 210, 490);
POINT_COLOR = BLUE;
LCD_DrawCircle(400, 400, 80);
printf(" LCD显示演示完成\r\n");
}
int main(void)
{
hardware_init();
LedManager::instance().init_all();
{
UartConfig uart_cfg;
uart_cfg.baudrate = 9600;
UartBus::default_instance().init(uart_cfg);
}
systick_config();
software_delay_ms(100);
printf("系统时钟调试信息:\r\n");
printf(" 时钟源: %s\r\n", get_clock_source_str());
printf(" 系统频率: %s\r\n", get_system_clock_str());
printf(" SystemCoreClock变量: %lu Hz\r\n", SystemCoreClock);
uart_send_string("Direct UART test: Hello World!\r\n");
printf("printf test: Hello World!\r\n");
printf("SysTick测试: 开始1秒延时...\r\n");
delay_1ms(1000);
printf("SysTick测试: 1秒延时完成\r\n");
printf("SysTick精确延时测试: 开始100ms x 10次延时...\r\n");
for (int i = 0; i < 10; i++)
{
delay_1ms(100);
printf(" Tick %d\r\n", i + 1);
}
printf("SysTick精确延时测试: 完成\r\n");
printf("\r\n");
// 暂时注释掉 SDRAM 和 SPI Flash,只测试 LCD
// printf("开始SDRAM驱动测试 (型号: W9825G6KH-6I)...\r\n");
// printf("\r\n");
// test_sdram_driver();
// printf("\r\n");
// printf("开始外部SPI Flash测试...\r\n");
// printf("\r\n");
// test_external_spi_flash();
// printf("\r\n");
printf("开始LCD显示测试...\r\n");
printf(" 注意:LCD和SDRAM共享EXMC数据总线D0-D15\r\n");
printf(" LCD使用NOR/PSRAM控制器(NE3/PG12, 地址0x6C000000)\r\n");
printf(" SDRAM使用SDRAM控制器(SDNE0/PC2, 地址0xC0000000)\r\n");
printf(" 两个控制器独立工作,互不干扰\r\n");
printf("\r\n");
lcd_display_demo();
printf("LCD显示测试完成\r\n");
printf("\r\n");
printf("进入主循环: LED闪烁\r\n");
while (1)
{
LedManager::instance().led(1).on();
delay_1ms(500);
LedManager::instance().led(1).off();
delay_1ms(500);
}
}
+118
View File
@@ -0,0 +1,118 @@
#include "gd32f4xx.h"
#include "systick.h"
#include "../../libs/thirdparty/GD32F4xx_Official/LCD_TOUCH_MCU_LiangShanPi/Hardware/usart0/usart0.h"
#include <stdio.h>
// LED引脚定义 - 梁山Pi开发板使用PD7作为LED1
#define LED_PORT GPIOD
#define LED_PIN GPIO_PIN_7
// 简单软件延时函数
static void software_delay_ms(uint32_t ms)
{
// 基于16MHz时钟的粗略延时
for(volatile uint32_t i = 0; i < ms * 8000; i++);
}
// LED闪烁函数
static void led_blink(uint8_t times, uint16_t on_ms, uint16_t off_ms)
{
for(int i = 0; i < times; i++) {
gpio_bit_set(LED_PORT, LED_PIN);
software_delay_ms(on_ms);
gpio_bit_reset(LED_PORT, LED_PIN);
software_delay_ms(off_ms);
}
}
// 直接串口发送函数(不使用printf)
static void uart_send_string(const char *str)
{
while(*str) {
usart_data_transmit(USART0, (uint8_t)(*str));
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
str++;
}
}
int main(void)
{
// ===== 第1步:时钟初始化 =====
// 注意:hardware_init.c应该在启动时已调用SystemInit()
// 确保系统时钟为16MHz
// ===== 第2步:LED初始化 =====
// 启用GPIOD时钟
rcu_periph_clock_enable(RCU_GPIOD);
// 配置PD7为推挽输出
gpio_mode_set(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_PIN);
gpio_output_options_set(LED_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED_PIN);
// 初始状态:LED灭
gpio_bit_reset(LED_PORT, LED_PIN);
// ===== 第3步:LED测试 =====
// 快速闪烁3次确认系统正常运行
led_blink(3, 100, 100);
software_delay_ms(500);
// ===== 第4步:串口初始化 =====
// 初始化串口调试输出(USART0, PA9/PA10, 9600 baud
usart0_init();
// ===== 第5步:串口测试 =====
// 发送测试字符串
uart_send_string("\r\n\r\n=== 最小系统测试程序 ===\r\n");
uart_send_string("系统时钟: 16MHz IRC16M\r\n");
uart_send_string("串口波特率: 9600\r\n");
uart_send_string("LED引脚: PD7\r\n");
uart_send_string("开始循环测试...\r\n");
// ===== 第6步:SysTick初始化 =====
// 初始化SysTick定时器(1ms中断)
systick_config();
// 等待SysTick稳定
for(volatile uint32_t i = 0; i < 100000; i++);
// ===== 第7步:主循环 =====
// 循环发送状态信息并闪烁LED
uint32_t counter = 0;
while(1) {
counter++;
// 发送状态信息
char msg[64];
// 使用简单的字符拼接,避免sprintf
uart_send_string("计数: ");
// 发送十进制计数器
uint32_t temp = counter;
char buf[12];
int idx = 0;
if(temp == 0) {
uart_send_string("0");
} else {
// 反向构建数字字符串
while(temp > 0) {
buf[idx++] = '0' + (temp % 10);
temp /= 10;
}
// 反向发送
while(idx > 0) {
usart_data_transmit(USART0, (uint8_t)buf[--idx]);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
}
uart_send_string(" - LED闪烁\r\n");
// 闪烁LED
led_blink(1, 200, 200);
// 延时2秒
for(volatile uint32_t i = 0; i < 2000000; i++);
}
}
+23
View File
@@ -0,0 +1,23 @@
#include "monitor_task.h"
#include "config.h"
ret_code_t monitor_task_init(void)
{
return RET_OK;
}
ret_code_t monitor_task_start(void)
{
return RET_OK;
}
ret_code_t monitor_task_stop(void)
{
return RET_OK;
}
void monitor_task_main(void *arg)
{
while (1) {
}
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef __MONITOR_TASK_H__
#define __MONITOR_TASK_H__
#include "common_types.h"
ret_code_t monitor_task_init(void);
ret_code_t monitor_task_start(void);
ret_code_t monitor_task_stop(void);
void monitor_task_main(void *arg);
#endif
+23
View File
@@ -0,0 +1,23 @@
#include "work_task.h"
#include "config.h"
ret_code_t work_task_init(void)
{
return RET_OK;
}
ret_code_t work_task_start(void)
{
return RET_OK;
}
ret_code_t work_task_stop(void)
{
return RET_OK;
}
void work_task_main(void *arg)
{
while (1) {
}
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef __WORK_TASK_H__
#define __WORK_TASK_H__
#include "common_types.h"
ret_code_t work_task_init(void);
ret_code_t work_task_start(void);
ret_code_t work_task_stop(void);
void work_task_main(void *arg);
#endif