diff options
Diffstat (limited to 'cm3cpp/usart.hpp')
-rw-r--r-- | cm3cpp/usart.hpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/cm3cpp/usart.hpp b/cm3cpp/usart.hpp new file mode 100644 index 0000000..68f8bc5 --- /dev/null +++ b/cm3cpp/usart.hpp @@ -0,0 +1,206 @@ +/* + * This file is part of the libopencm3_cpp_extensions project. + * hosted at http://github.com/thirdpin/libopencm3_cpp_extensions + * + * Copyright (C) 2016 Third Pin LLC + * Written by Anastasiia Lazareva <a.lazareva@thirdpin.ru> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* +USART C++ Wrapper of libopencm3 library for STM32F2, STM32F4 +*/ + +#ifndef CM3CPP_USART_H_ +#define CM3CPP_USART_H_ + +// GENERAL INCLUDES +#include <cstdint> + +// LIBOPENCM3 INCLUDES +#include <libopencm3/stm32/usart.h> +#ifdef STM32F2 +#include <libopencm3/stm32/f2/nvic.h> +#endif +#ifdef STM32F4 +#include <libopencm3/stm32/f4/nvic.h> +#endif + +// CM3CPP INCLUDES +#include "gpio.hpp" +#include "irq/irq.hpp" +#include "private/assert.h" + +namespace cm3cpp { + +namespace usart { + +enum DataBits : uint8_t +{ + _8 = 8, + _9 = 9 +}; + +enum Mode : uint16_t +{ + RX = USART_MODE_RX, + TX = USART_MODE_TX, + RX_TX = USART_MODE_TX_RX +}; + +enum StopBits : uint16_t +{ + _0_5 = USART_STOPBITS_0_5, + _1 = USART_STOPBITS_1, + _1_5 = USART_STOPBITS_1_5, + _2 = USART_STOPBITS_2 +}; + +enum Parity : uint16_t +{ + PAR_NONE = USART_PARITY_NONE, + PAR_EVEN = USART_PARITY_EVEN, + PAR_ODD = USART_PARITY_ODD +}; + +enum FlowControl : uint16_t +{ + NONE = USART_FLOWCONTROL_NONE, + RTS = USART_FLOWCONTROL_RTS, + CTS = USART_FLOWCONTROL_CTS, + RTS_CTS = USART_FLOWCONTROL_RTS_CTS +}; + +class Usart +{ + public: + using Gpio = gpio::Gpio; + + enum class Flag : uint16_t + { + TRANSMIT_COMPLETE = USART_SR_TC, + TX_BUFFER_EMPTY = USART_SR_TXE, + RX_NOT_EMPTY = USART_SR_RXNE, + }; + + struct Settings + { + uint32_t baud_rate; + DataBits word_length; + StopBits stop_bits; + Parity parity; + Mode mode; + FlowControl flow_control; + }; + + struct LowLevelConfig + { + uint8_t usart_number; + gpio::Gpio::Pinout tx; + gpio::Gpio::Pinout rx; + uint8_t nvic_priority; + }; + + Usart() = default; + + Usart(LowLevelConfig config, Settings settings); + + void init(LowLevelConfig config, Settings settings); + + void deinit(); + + void set_settings(Settings settings); + + bool get_flag_status(Flag flag) + { + return usart_get_flag(_usart, (uint16_t)flag); + } + + bool interrupt_source_rx() + { + return (((USART_CR1(_usart) & USART_CR1_RXNEIE) != 0) && + usart_get_flag(_usart, USART_SR_RXNE)); + } + + bool interrupt_source_tx() + { + return (((USART_CR1(_usart) & USART_CR1_TXEIE) != 0) && + usart_get_flag(_usart, USART_SR_TXE)); + } + + bool interrupt_source_TC() + { + return (((USART_CR1(_usart) & USART_CR1_TCIE) != 0) && + usart_get_flag(_usart, USART_SR_TC)); + } + + void clear_tc_flag() { USART_SR(_usart) = ~USART_SR_TC; } + + void enable_irq() { nvic_enable_irq(_usart_nvic); } + + void disable_irq() { nvic_disable_irq(_usart_nvic); } + + void enable_rx_interrupt() { usart_enable_rx_interrupt(_usart); } + + void enable_tx_interrupt() { usart_enable_tx_interrupt(_usart); } + + void enable_tc_interrupt() { USART_CR1(_usart) |= USART_CR1_TCIE; } + + void disable_rx_interrupt() { usart_disable_rx_interrupt(_usart); } + + void disable_tx_interrupt() { usart_disable_tx_interrupt(_usart); } + + void disable_tc_interrupt() { USART_CR1(_usart) &= ~USART_CR1_TCIE; } + + bool is_framing_error() { return (USART_SR(_usart) & USART_SR_FE) != 0; } + + bool is_overrun_error() { return (USART_SR(_usart) & USART_SR_IDLE) != 0; } + + bool is_any_error_occurred() + { + return (USART_SR(_usart) & + (USART_SR_ORE | USART_SR_FE | USART_SR_PE | USART_SR_NE)) != 0; + } + + uint32_t get_sr_reg() { return USART_SR(_usart); } + + bool is_data_received() { return (USART_SR(_usart) & USART_SR_RXNE) != 0; } + + bool is_data_sended() { return (USART_SR(_usart) & USART_SR_TXE) != 0; } + + void write_blocking(uint16_t data) { usart_send_blocking(_usart, data); } + + void write(uint16_t data) { usart_send(_usart, data); } + + uint16_t read() { return usart_recv(_usart); } + + uint16_t read_blocking() { return usart_recv_blocking(_usart); } + + auto get_irq() { return static_cast<Interrupt>(_usart_nvic); } + + protected: + Gpio _rx; + Gpio _tx; + uint32_t _usart; + uint32_t _usart_nvic; + + Mode _mode; +}; + +} // namespace usart + +} // namespace cm3cpp + +#endif /* CM3CPP_USART_H_ */ |