From f94f7f0d682edd384b691d4306ac70913284fd57 Mon Sep 17 00:00:00 2001 From: Thomas Klaehn Date: Fri, 8 Jan 2021 10:20:09 +0100 Subject: [PATCH] Add basic C++ Uart driver --- platform/stm32g0xx/Uart.cc | 80 ++++++++++++++++++++++++++++++++++++++ platform/stm32g0xx/Uart.h | 29 ++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 platform/stm32g0xx/Uart.cc create mode 100644 platform/stm32g0xx/Uart.h diff --git a/platform/stm32g0xx/Uart.cc b/platform/stm32g0xx/Uart.cc new file mode 100644 index 0000000..23ab7d6 --- /dev/null +++ b/platform/stm32g0xx/Uart.cc @@ -0,0 +1,80 @@ +#include "platform/stm32g0xx/Gpio.h" +#include "platform/stm32g0xx/Uart.h" + +using namespace perinet::platform::stm32g0xx; + +Uart::Uart(UartDevice device, uint32_t baud_rate) +{ + uint32_t tx_pin = 2; + uint32_t rx_pin = 3; + Gpio::Port port = Gpio::Port::PORT_A; + switch(device) { + case UartDevice::UART_2: + this->uart = USART2; + RCC->APBENR1 |= RCC_APBENR1_USART2EN; + break; + + case UartDevice::UART_3: + this->uart = USART3; + RCC->APBENR1 |= RCC_APBENR1_USART3EN; + + // FIXME: Set pin confing accordingly + break; + + case UartDevice::UART_4: + this->uart = USART4; + RCC->APBENR1 |= RCC_APBENR1_USART4EN; + + // FIXME: Set pin confing accordingly + break; + } + + Gpio tx_gpio(port, tx_pin, Gpio::Mode::MODE_AF_PP, Gpio::Pullup::PULLUP, + Gpio::AlternateFunction::ALTERNATE_FUNCTION_1); + Gpio rx_gpio(port, rx_pin, Gpio::Mode::MODE_AF_PP, Gpio::Pullup::PULLUP, + Gpio::AlternateFunction::ALTERNATE_FUNCTION_1); + + // Disable UART + this->uart->CR1 &= ~USART_CR1_UE; + + // USART CR1 Configuration + uint32_t tmp = this->uart->CR1; + tmp &= ~((USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8| USART_CR1_FIFOEN)); + tmp |= (USART_CR1_TE | USART_CR1_RE); // RX and TX mode + this->uart->CR1 = tmp; + + // USART CR2 Configuration + tmp = this->uart->CR2; + tmp &= ~(USART_CR2_STOP); + this->uart->CR2 = tmp; + + // USART CR3 Configuration + + // USART PRESC Configuration + + // USART BRR Configuration + tmp = ((64000000 + (baud_rate / 2)) / baud_rate); + this->uart->BRR = tmp; + + // In asynchronous mode, the following bits must be kept cleared: + // - LINEN and CLKEN bits in the USART_CR2 register, + // - SCEN, HDSEL and IREN bits in the USART_CR3 register. + this->uart->CR2 &= ~(USART_CR2_LINEN | USART_CR2_CLKEN); + this->uart->CR3 &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN); + + // Enable UART + this->uart->CR1 |= USART_CR1_UE; +} + +void Uart::sync_send(const uint8_t *buffer, uint32_t len) +{ + if (buffer == nullptr) { + return; + } + + for (uint32_t i = 0; i < len; i++) { + // wait for tx not full + while ((this->uart->ISR & USART_ISR_TXE_TXFNF) == 0); + this->uart->TDR = buffer[i]; + } +} diff --git a/platform/stm32g0xx/Uart.h b/platform/stm32g0xx/Uart.h new file mode 100644 index 0000000..368df32 --- /dev/null +++ b/platform/stm32g0xx/Uart.h @@ -0,0 +1,29 @@ +#ifndef __PLATFORM_STM32G0XX_UART_H__ +#define __PLATFORM_STM32G0XX_UART_H__ + +#include + +#include "stm32g0xx.h" + +namespace perinet::platform::stm32g0xx { + +class Uart +{ +public: + enum class UartDevice + { + UART_2, + UART_3, + UART_4 + }; + + Uart(UartDevice, uint32_t); + void sync_send(const uint8_t *, uint32_t); + +private: + USART_TypeDef * uart; +}; + +} + +#endif