Files
lishanpi/drv/uart/uart_driver.cpp
T
hm 2b9622f565 refactor: UartBus全面重构为USART,支持直接构造即可用
- UartBus -> USART (类名更符合外设命名规范)
- 构造函数 USART(UartPort port, uint32_t baudrate) 自动完成GPIO+外设初始化
- 移除default_instance()单例模式,移除init()/deinit()/irq_handler()
- 新增reinit(baudrate)支持时钟切换后波特率重新校准
- 新增static setDefault()用于printf路由选择
- 移除UartConfig配置结构体
- 更新iap.h/iap.cpp中UartBus引用为USART
- 更新main.cpp使用新USART构造模式
2026-04-27 11:14:22 +08:00

261 lines
6.6 KiB
C++

#include "uart_driver.h"
#include "gd32f4xx.h"
#include <cstddef>
#include <cstdio>
#include <cerrno>
#include <sys/stat.h>
#include <sys/unistd.h>
struct uart_hw_config_t {
uint32_t uart_base;
rcu_periph_enum rcu_clock;
uint32_t gpio_port;
rcu_periph_enum gpio_rcu;
uint32_t tx_pin;
uint32_t rx_pin;
uint32_t af;
};
static constexpr uart_hw_config_t uart_hw_map[] = {
{USART0, RCU_USART0, GPIOA, RCU_GPIOA, GPIO_PIN_9, GPIO_PIN_10, GPIO_AF_7},
{USART1, RCU_USART1, GPIOA, RCU_GPIOA, GPIO_PIN_2, GPIO_PIN_3, GPIO_AF_7},
{USART2, RCU_USART2, GPIOB, RCU_GPIOB, GPIO_PIN_10, GPIO_PIN_11, GPIO_AF_7},
{UART3, RCU_UART3, GPIOC, RCU_GPIOC, GPIO_PIN_10, GPIO_PIN_11, GPIO_AF_7},
{UART4, RCU_UART4, GPIOC, RCU_GPIOC, GPIO_PIN_12, GPIO_PIN_2, GPIO_AF_7},
{USART5, RCU_USART5, GPIOD, RCU_GPIOD, GPIO_PIN_2, GPIO_PIN_3, GPIO_AF_7},
{UART6, RCU_UART6, GPIOG, RCU_GPIOG, GPIO_PIN_6, GPIO_PIN_7, GPIO_AF_7},
};
USART *USART::default_ = nullptr;
USART::USART(UartPort port, uint32_t baudrate)
: port_(port), baudrate_(baudrate)
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(uart_hw_map) / sizeof(uart_hw_map[0])) {
return;
}
const uart_hw_config_t &hw = uart_hw_map[port_idx];
if (hw.uart_base == 0) {
return;
}
rcu_periph_clock_enable(hw.rcu_clock);
rcu_periph_clock_enable(hw.gpio_rcu);
gpio_af_set(hw.gpio_port, hw.af, hw.tx_pin | hw.rx_pin);
gpio_mode_set(hw.gpio_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, hw.tx_pin | hw.rx_pin);
gpio_output_options_set(hw.gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, hw.tx_pin | hw.rx_pin);
usart_deinit(hw.uart_base);
usart_baudrate_set(hw.uart_base, baudrate_);
usart_receive_config(hw.uart_base, USART_RECEIVE_ENABLE);
usart_transmit_config(hw.uart_base, USART_TRANSMIT_ENABLE);
usart_enable(hw.uart_base);
initialized_ = true;
}
USART::~USART()
{
if (initialized_) {
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx < sizeof(uart_hw_map) / sizeof(uart_hw_map[0])) {
usart_disable(uart_hw_map[port_idx].uart_base);
}
initialized_ = false;
}
if (default_ == this) {
default_ = nullptr;
}
}
RetCode USART::send_byte(uint8_t data)
{
if (!initialized_) return RET_NOT_INITIALIZED;
uint8_t port_idx = static_cast<uint8_t>(port_);
const uart_hw_config_t &hw = uart_hw_map[port_idx];
while (RESET == usart_flag_get(hw.uart_base, USART_FLAG_TBE));
usart_data_transmit(hw.uart_base, data);
while (RESET == usart_flag_get(hw.uart_base, USART_FLAG_TC));
return RET_OK;
}
RetCode USART::send_data(const uint8_t *data, uint32_t len)
{
if (!initialized_) return RET_NOT_INITIALIZED;
if (data == nullptr || len == 0) return RET_INVALID_PARAM;
uint8_t port_idx = static_cast<uint8_t>(port_);
const uart_hw_config_t &hw = uart_hw_map[port_idx];
for (uint32_t i = 0; i < len; i++) {
while (RESET == usart_flag_get(hw.uart_base, USART_FLAG_TBE));
usart_data_transmit(hw.uart_base, data[i]);
}
while (RESET == usart_flag_get(hw.uart_base, USART_FLAG_TC));
return RET_OK;
}
RetCode USART::receive_byte(uint8_t *data, uint32_t timeout_ms)
{
if (!initialized_) return RET_NOT_INITIALIZED;
if (data == nullptr) return RET_INVALID_PARAM;
uint8_t port_idx = static_cast<uint8_t>(port_);
const uart_hw_config_t &hw = uart_hw_map[port_idx];
if (timeout_ms == 0) {
while (RESET == usart_flag_get(hw.uart_base, USART_FLAG_RBNE));
*data = static_cast<uint8_t>(usart_data_receive(hw.uart_base));
return RET_OK;
}
uint32_t timeout = timeout_ms * 10000;
while (RESET == usart_flag_get(hw.uart_base, USART_FLAG_RBNE)) {
if (--timeout == 0) {
return RET_TIMEOUT;
}
}
*data = static_cast<uint8_t>(usart_data_receive(hw.uart_base));
return RET_OK;
}
void USART::reinit(uint32_t baudrate)
{
if (!initialized_) return;
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(uart_hw_map) / sizeof(uart_hw_map[0])) return;
const uart_hw_config_t &hw = uart_hw_map[port_idx];
baudrate_ = baudrate;
usart_disable(hw.uart_base);
usart_baudrate_set(hw.uart_base, baudrate_);
usart_enable(hw.uart_base);
}
void USART::setDefault(USART *uart)
{
default_ = uart;
}
extern "C" int _write(int file, char *ptr, int len)
{
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
USART *uart = USART::defaultInstance();
if (uart) {
uart->send_data(reinterpret_cast<const uint8_t *>(ptr), static_cast<uint32_t>(len));
}
return len;
}
errno = EBADF;
return -1;
}
extern "C" int _read(int file, char *ptr, int len)
{
(void)file;
(void)ptr;
(void)len;
errno = ENOSYS;
return -1;
}
extern "C" int _close(int file)
{
(void)file;
return -1;
}
extern "C" off_t _lseek(int file, off_t ptr, int dir)
{
(void)file;
(void)ptr;
(void)dir;
return 0;
}
extern "C" int _fstat(int file, struct stat *st)
{
(void)file;
st->st_mode = S_IFCHR;
return 0;
}
extern "C" int _isatty(int file)
{
if (file == STDOUT_FILENO || file == STDERR_FILENO || file == STDIN_FILENO) {
return 1;
}
return 0;
}
extern "C" int _getpid(void)
{
return 1;
}
extern "C" int _kill(int pid, int sig)
{
(void)pid;
(void)sig;
errno = EINVAL;
return -1;
}
extern "C" void _exit(int status)
{
(void)status;
while (1);
}
/* C-compatible wrappers for legacy code */
extern "C" {
static USART uart_0(UartPort::_0);
static USART uart_1(UartPort::_1);
static USART uart_2(UartPort::_2);
static USART uart_3(UartPort::_3);
static USART uart_4(UartPort::_4);
static USART uart_5(UartPort::_5);
static USART uart_6(UartPort::_6);
static USART *uart_instances[] = {
&uart_0, &uart_1, &uart_2, &uart_3, &uart_4, &uart_5, &uart_6,
};
static uint8_t uart_inited[7] = {0};
int uart_init(uint8_t port, uint32_t baudrate)
{
if (port >= 7) return -1;
uart_inited[port] = 1;
return 0;
}
int uart_send_byte(uint8_t port, uint8_t data)
{
if (port >= 7 || !uart_inited[port]) return -1;
return uart_instances[port]->send_byte(data) == RET_OK ? 0 : -1;
}
int uart_send_data(uint8_t port, const uint8_t *data, uint32_t len)
{
if (port >= 7 || !uart_inited[port]) return -1;
return uart_instances[port]->send_data(data, len) == RET_OK ? 0 : -1;
}
int uart_receive_byte(uint8_t port, uint8_t *data, uint32_t timeout_ms)
{
if (port >= 7 || !uart_inited[port]) return -1;
return uart_instances[port]->receive_byte(data, timeout_ms) == RET_OK ? 0 : -1;
}
} /* extern "C" */