/** * @file usart0.cpp * @brief USART0 串口模块实现与 printf 重定向。 */ #include "main.h" #include "device/usart0.h" #include "sys/config.h" uint8_t Usart0::s_txBuf[Usart0::kTxBufSize]; volatile uint16_t Usart0::s_txHead = 0U; volatile uint16_t Usart0::s_txTail = 0U; uint16_t Usart0::nextIndex(uint16_t idx) { return (idx + 1U) % kTxBufSize; } bool Usart0::isBufferFull() { return nextIndex(s_txHead) == s_txTail; } bool Usart0::isBufferEmpty() { return s_txHead == s_txTail; } int Usart0::putChar(int ch, FILE *f) { (void)f; uint16_t next = nextIndex(s_txHead); while(next == s_txTail) { /* 缓冲满,忙等重试 */ } s_txBuf[s_txHead] = static_cast(ch); s_txHead = next; usart_interrupt_enable(USART0, USART_INT_TBE); return ch; } void Usart0::onInterrupt() { if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_TBE) != RESET) { if(!isBufferEmpty()) { usart_data_transmit(USART0, s_txBuf[s_txTail]); s_txTail = nextIndex(s_txTail); } if(isBufferEmpty()) { usart_interrupt_disable(USART0, USART_INT_TBE); } } } void Usart0::configurePins() { rcu_periph_clock_enable(RCU_GPIOA); gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); } void Usart0::init() { rcu_periph_clock_enable(RCU_USART0); usart_deinit(USART0); usart_baudrate_set(USART0, CONFIG_USART0_BAUDRATE); usart_word_length_set(USART0, USART_WL_8BIT); usart_stop_bit_set(USART0, USART_STB_1BIT); usart_parity_config(USART0, USART_PM_NONE); usart_receive_config(USART0, USART_RECEIVE_ENABLE); usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); usart_enable(USART0); nvic_irq_enable(USART0_IRQn, 2U, 0U); } /* ----- 中断入口 / printf 重定向的 C 包装 --------------------------- */ extern "C" int fputc(int ch, FILE *f) { return Usart0::putChar(ch, f); } extern "C" void USART0_IRQHandler(void) { Usart0::onInterrupt(); }