Files
lishanpi/app/main.cpp
T

542 lines
14 KiB
C++

#include "gd32f4xx.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 "touch.h"
#include <cstdio>
#include <cstring>
__attribute__((section(".sdram"))) uint8_t sdram_big_buffer[1024 * 1024];
static void delay_16m(uint32_t ms)
{
for (volatile uint32_t i = 0; i < ms * 4000U; i++)
;
}
static void led_pattern(uint8_t p)
{
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 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;
}
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 ? "通过" : "失败");
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 ? "通过" : "失败");
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");
}
static void test_lcd(void)
{
Lcd &lcd = Lcd::instance();
printf("\r\n===== LCD 功能测试 =====\r\n");
printf(" LCD_Init...\r\n");
lcd.init();
printf(" LCD ID: %s\r\n", lcd.idString());
delay_1ms(500);
uint16_t bands[4] = {Lcd::RED, Lcd::GREEN, Lcd::BLUE, Lcd::WHITE};
for (int i = 0; i < 4; i++)
{
int y0 = i * 200;
int y1 = y0 + 199;
lcd.blockWrite(0, 479, y0, y1);
lcd.writeRamPrepare();
for (int p = 0; p < 480 * 200; p++)
lcd.writeRam(bands[i]);
__DSB();
}
delay_1ms(3000);
printf(" LCD_Clear(BLACK)\r\n");
lcd.clear(Lcd::BLACK);
delay_1ms(500);
printf(" LCD_Clear(RED)\r\n");
lcd.clear(Lcd::RED);
delay_1ms(500);
printf("LCD 测试完成\r\n");
delay_1ms(2000);
}
static void test_sdram_after_lcd(void)
{
printf("\r\n===== SDRAM 数据保持验证 (LCD 操作后) =====\r\n");
bool ok = true;
volatile uint16_t *sram16 = (volatile uint16_t *)0xC0000000;
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);
ok = false;
}
}
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++)
{
uint32_t val = sram32[i];
if (val != expected_32[i])
{
printf(" 32位错误 @ [%lu]: 期望=0x%08lX, 读取=0x%08lX\r\n", i, expected_32[i], val);
ok = false;
}
}
printf(" SDRAM 数据保持: %s\r\n", ok ? "通过 (LCD 未影响 SDRAM)" : "失败");
}
static void concurrent_loop(void)
{
Lcd &lcd = Lcd::instance();
printf("\r\n===== 全部外设并发运行 =====\r\n");
lcd.clear(Lcd::GREEN);
delay_1ms(500);
uint32_t counter = 0;
volatile uint16_t *sram16 = (volatile uint16_t *)0xC0000000;
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);
LedManager::instance().led(0).off();
LedManager::instance().led(1).on();
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");
lcd.clear(Lcd::BLUE);
delay_1ms(1000);
}
static void test_touch(void)
{
Lcd &lcd = Lcd::instance();
GT1151 &touch = GT1151::instance();
printf("\r\n===== Touch 测试 (多点触控) =====\r\n");
RetCode ret = touch.init();
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
};
const uint16_t BG_COLOR = 0x0841;
lcd.clear(BG_COLOR);
lcd.setForeground(Lcd::CYAN);
lcd.showString(10, 10, 460, 24, 16, 0, (uint8_t *)"=== Multi-Touch (5pt) ===");
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++)
{
lcd.setForeground(TP_COLORS[i]);
char lbl[8];
sprintf(lbl, "P%d: --", i);
lcd.showString(10, 52 + i * 18, 200, 18, 16, 0, (uint8_t *)lbl);
}
uint16_t last_x[5];
uint16_t last_y[5];
bool was_active[5];
for (uint8_t i = 0; i < GT1151::kMaxTouch; i++)
{
last_x[i] = 0xFFFF;
last_y[i] = 0xFFFF;
was_active[i] = false;
}
uint32_t idle_counter = 0;
GT1151::irq_flag = 0;
while (1)
{
if (GT1151::irq_flag)
{
GT1151::irq_flag = 0;
delay_1ms(5);
touch.scan(0);
idle_counter = 0;
uint8_t sta = touch.status();
uint8_t active_cnt = touch.activeCount();
uint8_t mask = sta & 0x1F;
for (uint8_t i = 0; i < GT1151::kMaxTouch; i++)
{
bool active = (mask & (1 << i)) != 0;
if (active)
{
uint16_t x = touch.x(i);
uint16_t y = touch.y(i);
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)
{
lcd.setForeground(TP_COLORS[i]);
lcd.drawLine(last_x[i], last_y[i], x, y);
}
lcd.setForeground(TP_COLORS[i]);
lcd.fillCircle(x, y, 5);
last_x[i] = x;
last_y[i] = y;
was_active[i] = true;
}
}
else
{
if (was_active[i])
{
lcd.setForeground(BG_COLOR);
lcd.fillCircle(last_x[i], last_y[i], 6);
lcd.setForeground(TP_COLORS[i]);
lcd.fillRectangle(10, 52 + i * 18, 200, 52 + i * 18 + 17);
lcd.showString(10, 52 + i * 18, 200, 18, 16, 0, (uint8_t *)"released");
last_x[i] = 0xFFFF;
last_y[i] = 0xFFFF;
was_active[i] = false;
}
}
}
printf("[TOUCH] cnt=%d sta=0x%02X", active_cnt, sta);
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
{
idle_counter++;
delay_1ms(10);
if (idle_counter > 500)
{
printf(" 无触摸超过 5 秒,退出 Touch 测试\r\n");
break;
}
}
}
lcd.clear(Lcd::BLUE);
printf(" Touch 测试完成\r\n");
delay_1ms(500);
}
int main(void)
{
LedManager::instance().init_all();
led_pattern(0x01);
{
UartConfig cfg;
cfg.baudrate = 9600;
UartBus::default_instance().init(cfg);
}
led_pattern(0x03);
printf("\r\n===== LSPi Board Bring-Up =====\r\n");
printf("Early boot: LED + UART at 16MHz\r\n");
uint32_t cs = RCU_CFG0 & RCU_CFG0_SCS;
printf("Clock source: ");
if (cs == RCU_SCSS_IRC16M)
printf("IRC16M (16MHz)\r\n");
else if (cs == RCU_SCSS_HXTAL)
printf("HXTAL (25MHz)\r\n");
else if (cs == RCU_SCSS_PLLP)
printf("PLL (168MHz)\r\n");
else
printf("UNKNOWN\r\n");
printf("SystemCoreClock: %lu Hz\r\n", SystemCoreClock);
for (int i = 0; i < 3; i++)
{
LedManager::instance().led(1).on();
delay_16m(200);
LedManager::instance().led(1).off();
delay_16m(200);
}
printf("LED blink OK\r\n");
printf("Initializing hardware...\r\n");
led_pattern(0x05);
HardwareInit::init();
{
UartConfig cfg;
cfg.baudrate = 9600;
UartBus::default_instance().init(cfg);
}
cs = RCU_CFG0 & RCU_CFG0_SCS;
printf("Clock after init: ");
if (cs == RCU_SCSS_PLLP)
printf("PLL (168MHz)\r\n");
else
printf("UNKNOWN\r\n");
printf("SystemCoreClock: %lu Hz\r\n", SystemCoreClock);
led_pattern(0x07);
printf("LedManager OK\r\n");
led_pattern(0x09);
printf("UartBus init OK\r\n");
led_pattern(0x0B);
systick_config();
delay_1ms(500);
printf("SysTick OK, delay_1ms available\r\n");
led_pattern(0x0C);
printf("\r\n========================================\r\n");
printf(" LSPi 全外设测试\r\n");
printf("========================================\r\n");
test_sdram_driver();
delay_1ms(500);
test_flash_driver();
delay_1ms(500);
test_lcd();
delay_1ms(500);
test_sdram_after_lcd();
delay_1ms(500);
concurrent_loop();
delay_1ms(500);
test_touch();
delay_1ms(500);
led_pattern(0x0F);
printf("\r\n===== 所有外设测试完成 =====\r\n");
printf("系统运行于 168MHz, Flash/SDRAM/LCD/UART/LED 全部正常\r\n");
uint32_t tick = 0;
while (1)
{
LedManager::instance().led(3).on();
delay_1ms(250);
LedManager::instance().led(3).off();
delay_1ms(250);
tick++;
if (tick % 4 == 0)
printf(".");
if (tick % 80 == 0)
printf(" [%lu s]\r\n", tick / 4);
}
}