fc10ef2e10
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
222 lines
5.3 KiB
C++
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" */
|