Files
lishanpi/drv/gpio/gpio_driver.cpp
T
hm fc10ef2e10 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
2026-04-26 16:24:42 +08:00

222 lines
5.3 KiB
C++

#include "gpio_driver.h"
#include "gd32f4xx.h"
struct GpioHwConfig {
uint32_t gpio_periph;
rcu_periph_enum rcu_clock;
};
static const GpioHwConfig gpio_hw_map[] = {
{ .gpio_periph = GPIOA, .rcu_clock = RCU_GPIOA },
{ .gpio_periph = GPIOB, .rcu_clock = RCU_GPIOB },
{ .gpio_periph = GPIOC, .rcu_clock = RCU_GPIOC },
{ .gpio_periph = GPIOD, .rcu_clock = RCU_GPIOD },
{ .gpio_periph = GPIOE, .rcu_clock = RCU_GPIOE },
{ .gpio_periph = GPIOF, .rcu_clock = RCU_GPIOF },
{ .gpio_periph = GPIOG, .rcu_clock = RCU_GPIOG },
{ .gpio_periph = GPIOH, .rcu_clock = RCU_GPIOH },
{ .gpio_periph = GPIOI, .rcu_clock = RCU_GPIOI },
};
static constexpr uint32_t gpio_mode_map[] = {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
GPIO_MODE_AF,
GPIO_MODE_ANALOG,
};
static constexpr uint32_t gpio_pupd_map[] = {
GPIO_PUPD_NONE,
GPIO_PUPD_PULLUP,
GPIO_PUPD_PULLDOWN,
};
static inline const GpioHwConfig *get_hw_config(GpioPort port)
{
uint8_t idx = static_cast<uint8_t>(port);
if (idx >= static_cast<uint8_t>(GpioPort::MAX))
return nullptr;
return &gpio_hw_map[idx];
}
GpioBus::GpioBus(GpioPort port)
: port_(port)
{
}
GpioBus::~GpioBus()
{
deinit();
}
RetCode GpioBus::init()
{
if (initialized_)
return RET_OK;
auto *hw = get_hw_config(port_);
if (!hw)
return RET_INVALID_PARAM;
rcu_periph_clock_enable(hw->rcu_clock);
initialized_ = true;
return RET_OK;
}
RetCode GpioBus::deinit()
{
if (!initialized_)
return RET_OK;
auto *hw = get_hw_config(port_);
if (!hw)
return RET_INVALID_PARAM;
gpio_deinit(hw->gpio_periph);
rcu_periph_clock_disable(hw->rcu_clock);
initialized_ = false;
return RET_OK;
}
GpioPin::GpioPin(GpioBus &bus, uint32_t pin, GpioConfig config)
: bus_(bus), pin_(pin), config_(config)
{
}
RetCode GpioPin::init()
{
if (initialized_)
return RET_OK;
auto *hw = get_hw_config(bus_.port_);
if (!hw)
return RET_INVALID_PARAM;
uint8_t mode_idx = static_cast<uint8_t>(config_.mode);
uint8_t pupd_idx = static_cast<uint8_t>(config_.pupd);
uint32_t mode = (mode_idx < 4) ? gpio_mode_map[mode_idx] : GPIO_MODE_INPUT;
uint32_t pupd = (pupd_idx < 3) ? gpio_pupd_map[pupd_idx] : GPIO_PUPD_NONE;
gpio_mode_set(hw->gpio_periph, mode, pupd, pin_);
if (config_.mode == GpioMode::OUTPUT || config_.mode == GpioMode::AF)
{
uint8_t otype = static_cast<uint8_t>(config_.output_type);
gpio_output_options_set(hw->gpio_periph, otype, config_.speed, pin_);
}
initialized_ = true;
return RET_OK;
}
RetCode GpioPin::set()
{
auto *hw = get_hw_config(bus_.port_);
if (!hw)
return RET_INVALID_PARAM;
gpio_bit_set(hw->gpio_periph, pin_);
return RET_OK;
}
RetCode GpioPin::reset()
{
auto *hw = get_hw_config(bus_.port_);
if (!hw)
return RET_INVALID_PARAM;
gpio_bit_reset(hw->gpio_periph, pin_);
return RET_OK;
}
RetCode GpioPin::toggle()
{
auto *hw = get_hw_config(bus_.port_);
if (!hw)
return RET_INVALID_PARAM;
gpio_bit_toggle(hw->gpio_periph, pin_);
return RET_OK;
}
uint8_t GpioPin::read() const
{
auto *hw = get_hw_config(bus_.port_);
if (!hw)
return 0;
return static_cast<uint8_t>(gpio_input_bit_get(hw->gpio_periph, pin_));
}
extern "C" {
static GpioBus gpio_bus_0(GpioPort::A);
static GpioBus gpio_bus_1(GpioPort::B);
static GpioBus gpio_bus_2(GpioPort::C);
static GpioBus gpio_bus_3(GpioPort::D);
static GpioBus gpio_bus_4(GpioPort::E);
static GpioBus gpio_bus_5(GpioPort::F);
static GpioBus gpio_bus_6(GpioPort::G);
static GpioBus gpio_bus_7(GpioPort::H);
static GpioBus gpio_bus_8(GpioPort::I);
static GpioBus *gpio_buses[] = {
&gpio_bus_0, &gpio_bus_1, &gpio_bus_2, &gpio_bus_3, &gpio_bus_4,
&gpio_bus_5, &gpio_bus_6, &gpio_bus_7, &gpio_bus_8,
};
static uint8_t gpio_inited[9] = {0};
static const uint32_t gpio_periph_tab[] = {
GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI
};
static const uint32_t gpio_mode_tab[] = {
GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF, GPIO_MODE_ANALOG
};
static const uint32_t gpio_pupd_tab[] = {
GPIO_PUPD_NONE, GPIO_PUPD_PULLUP, GPIO_PUPD_PULLDOWN
};
int gpio_init(uint8_t port, uint32_t pin, uint8_t mode, uint8_t pupd)
{
if (port >= 9) return -1;
if (!gpio_inited[port]) {
if (gpio_buses[port]->init() != RET_OK) return -1;
gpio_inited[port] = 1;
}
uint32_t m = (mode <= 3) ? gpio_mode_tab[mode] : GPIO_MODE_INPUT;
uint32_t p = (pupd <= 2) ? gpio_pupd_tab[pupd] : GPIO_PUPD_NONE;
gpio_mode_set(gpio_periph_tab[port], m, p, pin);
if (mode == GPIO_MODE_OUTPUT || mode == GPIO_MODE_AF) {
gpio_output_options_set(gpio_periph_tab[port], GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin);
}
return 0;
}
int gpio_set(uint8_t port, uint32_t pin)
{
if (port >= 9) return -1;
gpio_bit_set(gpio_periph_tab[port], pin);
return 0;
}
int gpio_reset(uint8_t port, uint32_t pin)
{
if (port >= 9) return -1;
gpio_bit_reset(gpio_periph_tab[port], pin);
return 0;
}
int gpio_toggle(uint8_t port, uint32_t pin)
{
if (port >= 9) return -1;
gpio_bit_toggle(gpio_periph_tab[port], pin);
return 0;
}
uint8_t gpio_read(uint8_t port, uint32_t pin)
{
if (port >= 9) return 0;
return (uint8_t)gpio_input_bit_get(gpio_periph_tab[port], pin);
}
} /* extern "C" */