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
+234
View File
@@ -0,0 +1,234 @@
#include "timer_driver.h"
#include "gd32f4xx.h"
#include <cstddef>
struct timer_hw_config_t {
uint32_t timer_periph;
rcu_periph_enum rcu_clock;
bool is_32bit;
bool is_advanced;
};
static constexpr timer_hw_config_t timer_hw_map[] = {
{TIMER0, RCU_TIMER0, false, true },
{TIMER1, RCU_TIMER1, true, false},
{TIMER2, RCU_TIMER2, false, false},
{TIMER3, RCU_TIMER3, false, false},
{TIMER4, RCU_TIMER4, true, false},
{TIMER5, RCU_TIMER5, false, false},
{TIMER6, RCU_TIMER6, false, false},
{TIMER7, RCU_TIMER7, false, true },
{TIMER8, RCU_TIMER8, false, false},
{TIMER9, RCU_TIMER9, false, false},
{TIMER10, RCU_TIMER10, false, false},
{TIMER11, RCU_TIMER11, false, false},
{TIMER12, RCU_TIMER12, false, false},
{TIMER13, RCU_TIMER13, false, false},
};
static uint8_t timer_irq_map(uint32_t timer_periph)
{
if (timer_periph == TIMER0) return TIMER0_UP_TIMER9_IRQn;
if (timer_periph == TIMER1) return TIMER1_IRQn;
if (timer_periph == TIMER2) return TIMER2_IRQn;
if (timer_periph == TIMER3) return TIMER3_IRQn;
if (timer_periph == TIMER4) return TIMER4_IRQn;
if (timer_periph == TIMER5) return 0;
if (timer_periph == TIMER6) return TIMER6_IRQn;
if (timer_periph == TIMER7) return TIMER7_UP_TIMER12_IRQn;
if (timer_periph == TIMER8) return TIMER0_BRK_TIMER8_IRQn;
if (timer_periph == TIMER9) return TIMER0_UP_TIMER9_IRQn;
if (timer_periph == TIMER10) return TIMER0_TRG_CMT_TIMER10_IRQn;
if (timer_periph == TIMER11) return TIMER7_BRK_TIMER11_IRQn;
if (timer_periph == TIMER12) return TIMER7_UP_TIMER12_IRQn;
if (timer_periph == TIMER13) return TIMER7_TRG_CMT_TIMER13_IRQn;
return 0;
}
TimerBus::TimerBus(TimerPort port)
: port_(port)
{
}
TimerBus::~TimerBus()
{
if (initialized_) {
deinit();
}
}
RetCode TimerBus::init(const TimerConfig &config)
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(timer_hw_map) / sizeof(timer_hw_map[0])) {
return RET_INVALID_PARAM;
}
const timer_hw_config_t &hw = timer_hw_map[port_idx];
if (hw.timer_periph == 0) {
return RET_NOT_SUPPORTED;
}
config_ = config;
rcu_periph_clock_enable(hw.rcu_clock);
timer_parameter_struct timer_para;
timer_struct_para_init(&timer_para);
timer_para.prescaler = static_cast<uint16_t>(config.prescaler - 1);
timer_para.period = config.period;
timer_para.alignedmode = TIMER_COUNTER_EDGE;
timer_para.counterdirection = TIMER_COUNTER_UP;
timer_para.clockdivision = TIMER_CKDIV_DIV1;
timer_para.repetitioncounter = 0U;
timer_init(hw.timer_periph, &timer_para);
if (config.mode == TimerMode::ONE_PULSE) {
timer_single_pulse_mode_config(hw.timer_periph, TIMER_SP_MODE_SINGLE);
}
if (config.use_interrupt) {
uint8_t irq = timer_irq_map(hw.timer_periph);
if (irq != 0) {
timer_interrupt_enable(hw.timer_periph, TIMER_INT_UP);
nvic_irq_enable(irq, 0, 0);
}
}
initialized_ = true;
return RET_OK;
}
RetCode TimerBus::deinit()
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(timer_hw_map) / sizeof(timer_hw_map[0])) {
return RET_INVALID_PARAM;
}
const timer_hw_config_t &hw = timer_hw_map[port_idx];
timer_disable(hw.timer_periph);
timer_interrupt_disable(hw.timer_periph, TIMER_INT_UP);
timer_deinit(hw.timer_periph);
rcu_periph_clock_disable(hw.rcu_clock);
initialized_ = false;
return RET_OK;
}
RetCode TimerBus::start()
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(timer_hw_map) / sizeof(timer_hw_map[0])) {
return RET_INVALID_PARAM;
}
if (!initialized_) return RET_NOT_INITIALIZED;
const timer_hw_config_t &hw = timer_hw_map[port_idx];
timer_enable(hw.timer_periph);
return RET_OK;
}
RetCode TimerBus::stop()
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(timer_hw_map) / sizeof(timer_hw_map[0])) {
return RET_INVALID_PARAM;
}
if (!initialized_) return RET_NOT_INITIALIZED;
const timer_hw_config_t &hw = timer_hw_map[port_idx];
timer_disable(hw.timer_periph);
return RET_OK;
}
RetCode TimerBus::set_period(uint32_t period)
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(timer_hw_map) / sizeof(timer_hw_map[0])) {
return RET_INVALID_PARAM;
}
if (!initialized_) return RET_NOT_INITIALIZED;
const timer_hw_config_t &hw = timer_hw_map[port_idx];
timer_autoreload_value_config(hw.timer_periph, period);
config_.period = period;
return RET_OK;
}
uint32_t TimerBus::get_counter() const
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(timer_hw_map) / sizeof(timer_hw_map[0])) {
return 0;
}
if (!initialized_) return 0;
const timer_hw_config_t &hw = timer_hw_map[port_idx];
return timer_counter_read(hw.timer_periph);
}
void timer_irq_handler(TimerPort port)
{
uint8_t port_idx = static_cast<uint8_t>(port);
if (port_idx >= sizeof(timer_hw_map) / sizeof(timer_hw_map[0])) {
return;
}
const timer_hw_config_t &hw = timer_hw_map[port_idx];
if (hw.timer_periph == 0) return;
if (timer_interrupt_flag_get(hw.timer_periph, TIMER_INT_UP) != RESET) {
timer_interrupt_flag_clear(hw.timer_periph, TIMER_INT_UP);
}
}
extern "C" {
static TimerBus timer_0(TimerPort::_0);
static TimerBus timer_1(TimerPort::_1);
static TimerBus timer_2(TimerPort::_2);
static TimerBus timer_3(TimerPort::_3);
static TimerBus timer_4(TimerPort::_4);
static TimerBus timer_5(TimerPort::_5);
static TimerBus timer_6(TimerPort::_6);
static TimerBus timer_7(TimerPort::_7);
static TimerBus timer_8(TimerPort::_8);
static TimerBus timer_9(TimerPort::_9);
static TimerBus timer_10(TimerPort::_10);
static TimerBus timer_11(TimerPort::_11);
static TimerBus timer_12(TimerPort::_12);
static TimerBus timer_13(TimerPort::_13);
static TimerBus *timer_instances[] = {
&timer_0, &timer_1, &timer_2, &timer_3, &timer_4, &timer_5, &timer_6,
&timer_7, &timer_8, &timer_9, &timer_10, &timer_11, &timer_12, &timer_13,
};
static uint8_t timer_inited[14] = {0};
int timer_bus_init(uint8_t port, uint32_t prescaler, uint32_t period)
{
if (port >= 14) return -1;
TimerConfig cfg;
cfg.prescaler = prescaler;
cfg.period = period;
RetCode ret = timer_instances[port]->init(cfg);
timer_inited[port] = (ret == RET_OK) ? 1 : 0;
return timer_inited[port] ? 0 : -1;
}
int timer_start(uint8_t port)
{
if (port >= 14 || !timer_inited[port]) return -1;
return timer_instances[port]->start() == RET_OK ? 0 : -1;
}
int timer_stop(uint8_t port)
{
if (port >= 14 || !timer_inited[port]) return -1;
return timer_instances[port]->stop() == RET_OK ? 0 : -1;
}
} /* extern "C" */