Files
lishanpi/app/main.cpp
T
hm cbad06d616 refactor(touch): 集成硬件 I2C 驱动并添加 EXTI 中断支持
- 将 touch 底层从软件 I2C 位冲切换为硬件 I2C0 (PB6/PB7)
- 修复 i2c_driver I2C0 引脚映射 (PB8/PB9 -> PB6/PB7)
- 重写 master_write_read() 实现正确的重复起始条件
- 添加 i2c_driver.h C API 声明供 C 代码调用
- 添加 GT1151 EXTI 中断 (PD11, EXTI11 下降沿触发)
- 删除 touch.h 中废弃的软件 I2C 函数声明
- test_touch() 改为中断驱动,无触摸时 I2C 总线空闲
2026-04-26 20:36:54 +08:00

561 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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>
// SDRAM 中分配的测试缓冲区
__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
// =============================================================
// 早期启动函数(16MHz,无 SysTick
// =============================================================
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);
}
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);
}
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]);
}
// 时钟切换到 168MHz 后重新配置 UART 波特率
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_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)
{
printf("\r\n===== LCD 功能测试 =====\r\n");
printf(" LCD_Init...\r\n");
LCD_Init();
printf(" LCD ID: %s\r\n", lcd_id);
delay_1ms(500);
uint16_t bands[4] = {RED, GREEN, BLUE, WHITE};
for (int i = 0; i < 4; i++) {
int y0 = i * 200;
int y1 = y0 + 199;
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(500);
printf(" LCD_Clear(RED)\r\n");
LCD_Clear(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)
{
printf("\r\n===== 全部外设并发运行 =====\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");
LCD_Clear(BLUE);
delay_1ms(1000);
}
// =============================================================
// Touch 测试
// =============================================================
static void test_touch(void)
{
printf("\r\n===== Touch 测试 (中断驱动) =====\r\n");
uint8_t ret = GT1151_Init();
if (ret != 0)
{
printf(" Touch 初始化失败 (ret=%d)\r\n", ret);
return;
}
printf(" Touch 初始化成功,等待触摸中断...\r\n");
LCD_Clear(0x0841);
POINT_COLOR = CYAN;
LCD_ShowString(10, 10, 460, 24, 16, 0, (uint8_t *)"=== Touch Test (IRQ) ===");
POINT_COLOR = WHITE;
LCD_ShowString(10, 35, 460, 24, 16, 0, (uint8_t *)"Touch screen now");
LCD_ShowString(10, 55, 300, 24, 16, 0, (uint8_t *)"IRQ driven, watch UART");
LCD_ShowString(10, 75, 200, 24, 16, 0, (uint8_t *)"X:0 Y:0");
uint16_t last_x = 0xFFFF;
uint16_t last_y = 0xFFFF;
uint32_t idle_counter = 0;
bool was_touching = false;
uint32_t iter = 0;
g_touch_irq_flag = 0;
while (1)
{
if (g_touch_irq_flag)
{
g_touch_irq_flag = 0;
delay_1ms(5);
GT1151_Scan(0);
if (tp_dev.sta & TP_PRES_DOWN)
{
idle_counter = 0;
uint16_t x = tp_dev.x[0];
uint16_t y = tp_dev.y[0];
printf("[TOUCH] iter=%lu sta=0x%02X x=%u y=%u\r\n",
(unsigned long)iter, tp_dev.sta, x, y);
if (x < lcddev.width && y < lcddev.height)
{
POINT_COLOR = BLACK;
LCD_FillRectangle(10, 75, 200, 95);
POINT_COLOR = GREEN;
char buf[24];
sprintf(buf, "X:%-3d Y:%-3d", x, y);
LCD_ShowString(10, 75, 200, 24, 16, 0, (uint8_t *)buf);
if (was_touching && last_x != 0xFFFF)
{
POINT_COLOR = MAGENTA;
LCD_DrawLine(last_x, last_y, x, y);
}
POINT_COLOR = YELLOW;
LCD_FillCircle(x, y, 4);
last_x = x;
last_y = y;
was_touching = true;
}
}
else
{
was_touching = false;
last_x = 0xFFFF;
last_y = 0xFFFF;
}
iter++;
}
else
{
idle_counter++;
delay_1ms(10);
if (idle_counter > 500)
{
printf(" 无触摸超过 5 秒,退出 Touch 测试\r\n");
break;
}
}
}
LCD_Clear(BLUE);
printf(" Touch 测试完成\r\n");
delay_1ms(500);
}
// =============================================================
// 主函数
// =============================================================
int main(void)
{
// ---- 早期启动: 16MHz,原始寄存器操作 ----
init_leds();
led_pattern(0x01);
init_usart0();
led_pattern(0x03);
uart_puts("\r\n===== LSPi Board Bring-Up =====\r\n");
uart_puts("Early boot: LED + UART at 16MHz\r\n");
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");
uart_puts("SystemCoreClock: ");
uart_putdec(SystemCoreClock);
uart_puts(" Hz\r\n");
// LED 闪烁验证
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("LED blink OK\r\n");
// ---- 硬件初始化: 切换到 168MHz ----
uart_puts("Initializing hardware...\r\n");
led_pattern(0x05);
hardware_init();
reinit_usart0_168m();
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");
uart_puts("SystemCoreClock: ");
uart_putdec(SystemCoreClock);
uart_puts(" Hz\r\n");
// ---- C++ 驱动初始化 ----
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);
{
UartConfig cfg;
cfg.baudrate = 9600;
UartBus::default_instance().init(cfg);
}
uart_puts("UartBus init OK\r\n");
// ---- SysTick 配置 ----
led_pattern(0x0B);
systick_config();
delay_1ms(500);
uart_puts("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) {
led_on(LED4_PORT, LED4_PIN);
delay_1ms(250);
led_off(LED4_PORT, LED4_PIN);
delay_1ms(250);
tick++;
if (tick % 4 == 0)
printf(".");
}
}