diff options
author | IvanOrfanidi <i.orfanidi@thirdpin.io> | 2019-05-31 17:37:45 +0300 |
---|---|---|
committer | IvanOrfanidi <i.orfanidi@thirdpin.io> | 2019-06-03 11:09:21 +0300 |
commit | f5ec1056a15d90bee6965dc43426212dd19c2117 (patch) | |
tree | 304becd3eedf269e1fa43192b20262aa306b4aaa | |
parent | e5bbcc02fa5cef76e1a4dea13f8aae125f12a95a (diff) |
Added USART and DMA drivers
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | cm3cpp_dma.cpp | 107 | ||||
-rw-r--r-- | cm3cpp_dma.hpp | 155 | ||||
-rw-r--r-- | cm3cpp_usart_dma.cpp | 202 | ||||
-rw-r--r-- | cm3cpp_usart_dma.hpp | 129 |
5 files changed, 595 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3780dfc..766c6d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,8 @@ target_sources(${PROJECT_NAME} INTERFACE ${CM3CPP_LOCATION}/cm3cpp_timer.cpp ${CM3CPP_LOCATION}/cm3cpp_usart_rb.cpp ${CM3CPP_LOCATION}/cm3cpp_usart.cpp - ${CM3CPP_LOCATION}/rs485.cpp + ${CM3CPP_LOCATION}/cm3cpp_usart_dma.cpp + ${CM3CPP_LOCATION}/cm3cpp_dma.cpp ) target_include_directories(${PROJECT_NAME} diff --git a/cm3cpp_dma.cpp b/cm3cpp_dma.cpp new file mode 100644 index 0000000..f7fbadc --- /dev/null +++ b/cm3cpp_dma.cpp @@ -0,0 +1,107 @@ +/** + ****************************************************************************** + * @file cm3cpp_dma + * @author + * @version V1.0 + * @date 05-2019 + * @brief This is file realise uart. + ****************************************************************************** + * @attention + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "cm3cpp_dma.hpp" + +// LIBOPENCM3 INCLUDES +#include <libopencm3/cm3/nvic.h> +#include <libopencm3/cm3/scs.h> +#include <libopencm3/stm32/rcc.h> + +namespace cm3cpp { + +namespace dma { + +Dma::Dma(const LowLevelConfig& config) : + _num_dma(config.num_dma), + _stream(config.stream), + _irq(config.irq) +{ + // Enable clock DMA + if (_num_dma == _1) { + rcc_periph_clock_enable(RCC_DMA1); + } + else { + rcc_periph_clock_enable(RCC_DMA2); + } + + // Reset channel + dma_stream_reset(_num_dma, _stream); + + // Config DMA + dma_set_priority(_num_dma, _stream, config.priority); + dma_set_memory_size(_num_dma, _stream, config.mem_size); + dma_set_peripheral_size(_num_dma, _stream, config.periph_size); + + if (config.periph_inc_mode == INCREMENTED_ENABLE) { + dma_enable_peripheral_increment_mode(_num_dma, _stream); + } + else { + dma_disable_peripheral_increment_mode(_num_dma, _stream); + } + + if (config.mem_inc_mode == INCREMENTED_ENABLE) { + dma_enable_memory_increment_mode(_num_dma, _stream); + } + else { + dma_disable_memory_increment_mode(_num_dma, _stream); + } + + if (config.mode == CIRCULAR) { + dma_enable_circular_mode(_num_dma, _stream); + } + + dma_set_transfer_mode(_num_dma, _stream, config.direction); + + dma_set_peripheral_address(_num_dma, _stream, config.peripheral_base_addr); + + dma_channel_select(_num_dma, _stream, config.channel); + + /// Configure interrupt + dma_enable_transfer_complete_interrupt(_num_dma, _stream); + enable_irq(); +} + +void Dma::set_memory_address(uint32_t address) const +{ + dma_set_memory_address(_num_dma, _stream, address); +} + +void Dma::set_data_counter(uint16_t len) const +{ + dma_set_number_of_data(_num_dma, _stream, len); +} + +void Dma::enable_stream() const +{ + dma_enable_stream(_num_dma, _stream); +} + +void Dma::disable_stream() const +{ + dma_disable_stream(_num_dma, _stream); +} + +void Dma::enable_irq() const +{ + nvic_enable_irq(_irq); +} + +void Dma::disable_irq() const +{ + nvic_disable_irq(_irq); +} +} + +} // namespace cm3cpp diff --git a/cm3cpp_dma.hpp b/cm3cpp_dma.hpp new file mode 100644 index 0000000..a5a21ec --- /dev/null +++ b/cm3cpp_dma.hpp @@ -0,0 +1,155 @@ +/** + ****************************************************************************** + * @file cm3cpp_dma.hpp + * @author + * @version V1.0 + * @date 05-2019 + * @brief This is file realise DMA. + ****************************************************************************** + * @attention + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#pragma once + +// LIBOPENCM3 INCLUDES +#include <libopencm3/stm32/dma.h> + +namespace cm3cpp { + +namespace dma { + +enum NumDma +{ + _1 = DMA1, + _2 = DMA2, +}; + +/// Streams for USARTs +enum Stream +{ + /** For DMA2 **/ + /// USART1 + USART1_TX_DMA2_STREAM = DMA_STREAM7, + USART1_RX_DMA2_STREAM = DMA_STREAM5, + + /// USART6 + USART6_TX_DMA2_STREAM = DMA_STREAM7, + USART6_RX_DMA2_STREAM = DMA_STREAM2, + /**************/ +}; + +/// Channels for USARTs +enum Channel +{ + /** For DMA2 **/ + /// USART1 + USART1_TX_DMA2_CHANNEL = DMA_SxCR_CHSEL_4, + USART1_RX_DMA2_CHANNEL = DMA_SxCR_CHSEL_4, + + /// USART6 + USART6_TX_DMA2_CHANNEL = DMA_SxCR_CHSEL_5, + USART6_RX_DMA2_CHANNEL = DMA_SxCR_CHSEL_5, + /**************/ +}; + +enum DataTransferDirection +{ + MEM_TO_PERIPHERAL = DMA_SxCR_DIR_MEM_TO_PERIPHERAL, + PERIPHERAL_TO_MEM = DMA_SxCR_DIR_PERIPHERAL_TO_MEM, + MEM_TO_MEM = DMA_SxCR_DIR_MEM_TO_MEM +}; + +/// Shows where or where data will be sent, to the periphery or memory +enum IncrementedMode +{ + INCREMENTED_DISABLE, + INCREMENTED_ENABLE +}; + +/// Shows how much the size will be increased for the periphery +enum DataSize +{ + PERIPHERAL_BYTE = DMA_SxCR_PSIZE_8BIT, + PERIPHERAL_HALF_WORD = DMA_SxCR_PSIZE_16BIT, + PERIPHERAL_WORD = DMA_SxCR_PSIZE_32BIT, + + MEMORY_BYTE = DMA_SxCR_MSIZE_8BIT, + MEMORY_HALF_WORD = DMA_SxCR_MSIZE_16BIT, + MEMORY_WORD = DMA_SxCR_MSIZE_32BIT, +}; + +/// DMA data recording mode, cyclic or normal +enum Mode +{ + NORMAL, + CIRCULAR +}; + +/// The priorities of DMA +enum Priority +{ + LOW = DMA_SxCR_PL_LOW, + MEDIUM = DMA_SxCR_PL_MEDIUM, + HIGH = DMA_SxCR_PL_HIGH, + VERY_HIGH = DMA_SxCR_PL_VERY_HIGH +}; + +/// Low level config for DMA +struct LowLevelConfig +{ + NumDma num_dma; + Stream stream; + Channel channel; + uint32_t peripheral_base_addr; + DataTransferDirection direction; + IncrementedMode periph_inc_mode; + IncrementedMode mem_inc_mode; + DataSize periph_size; + DataSize mem_size; + Mode mode; + Priority priority; + uint8_t irq; +}; + +/** + * Class hard DMA + */ +class Dma +{ + public: + Dma(const LowLevelConfig& config); + + void set_memory_address(uint32_t address) const; + + void enable_stream() const; + + void disable_stream() const; + + void set_data_counter(uint16_t len) const; + + void enable_irq() const; + + void disable_irq() const; + + /* These variables are made global for quick access */ + Stream _stream; ///< Shows the stream on which DMA is configured + NumDma _num_dma; ///< Number configured DMA + + protected: + Dma() = delete; /// Constructor default is delete + Dma(const Dma& a) = delete; /// Constructor copy is delete + Dma(const Dma&& a) = delete; /// Constructor move is delete + + Dma& operator=(const Dma&) = delete; /// Operator copy is delete + Dma& operator=(Dma&&) = delete; /// Operator move is delete + + private: + uint8_t _irq; ///< Number interrupt +}; + +} // namespace dma + +} // namespace cm3cpp // namespace cm3cpp diff --git a/cm3cpp_usart_dma.cpp b/cm3cpp_usart_dma.cpp new file mode 100644 index 0000000..a79306a --- /dev/null +++ b/cm3cpp_usart_dma.cpp @@ -0,0 +1,202 @@ +/** + ****************************************************************************** + * @file cm3cpp_usart_dma.cpp + * @author + * @version V1.0 + * @date 05-2019 + * @brief This is file realise uart. + ****************************************************************************** + * @attention + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "cm3cpp_usart_dma.hpp" + +#include <cm3cpp_config.h> +#include <libopencm3/stm32/rcc.h> +#include <libopencm3/stm32/usart.h> +#include <string.h> + +namespace cm3cpp { + +namespace usart_dma { + +/** + * Constructor USART-DMA + * @param usart_config - low level config usart + * @param settings - usart settings + * @param dma_tx_config - DMA config for transmission + * @param dma_rx_config - DMA config for receive + */ +UsartDma::UsartDma(const LowLevelConfigUsart& usart_config, + const Settings& settings, + const dma::LowLevelConfig& dma_tx_config, + const dma::LowLevelConfig& dma_rx_config) : + _dma_tx(dma_tx_config), + _dma_rx(dma_rx_config) +{ + // For reset and clock periph + rcc_periph_rst rcc_rst; + rcc_periph_clken rcc_clken; + + switch (usart_config.usart_number) { + case 1: { + _usart = USART1; + rcc_rst = RST_USART1; + rcc_clken = RCC_USART1; + break; + } + case 2: { + _usart = USART2; + rcc_rst = RST_USART2; + rcc_clken = RCC_USART2; + break; + } + case 3: { + _usart = USART3; + rcc_rst = RST_USART3; + rcc_clken = RCC_USART3; + break; + } + case 4: { + _usart = UART4; + rcc_rst = RST_UART4; + rcc_clken = RCC_UART5; + break; + } + case 5: { + _usart = UART5; + rcc_rst = RST_UART5; + rcc_clken = RCC_UART5; + break; + } + default: { + _usart = USART6; + rcc_rst = RST_USART6; + rcc_clken = RCC_USART6; + break; + } + } + + // Reset periph + rcc_periph_reset_pulse(rcc_rst); + // Clock enable + rcc_periph_clock_enable(rcc_clken); + + uint8_t af = GPIO_AF8; + if ((usart_config.usart_number >= 1) && (usart_config.usart_number <= 3)) { + af = GPIO_AF7; + } + + // Config GPIO + if (settings.mode == TX || settings.mode == RX_TX) { + // Pin transmit + port_config_clock_enable(usart_config.tx.port); + gpio_mode_setup(usart_config.tx.port, GPIO_MODE_AF, GPIO_PUPD_NONE, + usart_config.tx.pin); + + gpio_set_af(usart_config.tx.port, af, usart_config.tx.pin); + usart_enable_tx_dma(_usart); + } + + if (settings.mode == RX || settings.mode == RX_TX) { + // Pin receive + port_config_clock_enable(usart_config.rx.port); + gpio_mode_setup(usart_config.rx.port, GPIO_MODE_AF, GPIO_PUPD_NONE, + usart_config.rx.pin); + + gpio_set_af(usart_config.tx.port, af, usart_config.tx.pin); + gpio_set_output_options(usart_config.rx.port, GPIO_OTYPE_OD, + GPIO_OSPEED_100MHZ, usart_config.rx.pin); + usart_enable_rx_dma(_usart); + } + + // Config USART + init_uasrt(settings); + + // Enable USART + enable(); +} + +/** + * Enable clock port GPIO + * @param port - port GPIO + */ +void UsartDma::port_config_clock_enable(uint32_t port) const +{ + rcc_periph_clken clken; + if (port == GPIOA) { + clken = RCC_GPIOA; + } + else if (port == GPIOB) { + clken = RCC_GPIOB; + } + else if (port == GPIOC) { + clken = RCC_GPIOC; + } + else if (port == GPIOD) { + clken = RCC_GPIOD; + } + else if (port == GPIOE) { + clken = RCC_GPIOE; + } + else if (port == GPIOF) { + clken = RCC_GPIOF; + } + else if (port == GPIOG) { + clken = RCC_GPIOG; + } + + rcc_periph_clock_enable(clken); +} + +/** + * Config USART + * @param settings - settings for usart + */ +void UsartDma::init_uasrt(const Settings& settings) const +{ + // Setup parameters + usart_set_baudrate(_usart, settings.baud_rate); + usart_set_databits(_usart, settings.word_length); + usart_set_stopbits(_usart, settings.stop_bits); + usart_set_mode(_usart, settings.mode); + usart_set_parity(_usart, settings.parity); + usart_set_flow_control(_usart, settings.flow_control); +} + +/** + * Usart enable + */ +void UsartDma::enable() const +{ + usart_enable(_usart); +} + +/** + * Usart disable + */ +void UsartDma::disable() const +{ + usart_disable(_usart); +} + +/** + * Sending data to USART(not safe) + * @param data - data reference + * @param len - data length + */ +void UsartDma::write(uint8_t& data, uint16_t len) +{ + _dma_tx.set_memory_address((uint32_t)(&data)); + _dma_tx.set_data_counter(len); + + // Enable sending, disable it in the interrupt + _dma_tx.enable_stream(); +} + +} // namespace usart_dma + +} // namespace cm3cpp diff --git a/cm3cpp_usart_dma.hpp b/cm3cpp_usart_dma.hpp new file mode 100644 index 0000000..aa39c7d --- /dev/null +++ b/cm3cpp_usart_dma.hpp @@ -0,0 +1,129 @@ +/** + ****************************************************************************** + * @file cm3cpp_usart_dma.hpp + * @author + * @version V1.0 + * @date 05-2019 + * @brief This is file realise usart. + ****************************************************************************** + * @attention + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#pragma once + +// LIBOPENCM3 INCLUDES +#include <libopencm3/stm32/usart.h> + +// CM3CPP INCLUDES +#include "cm3cpp_dma.hpp" +#include "cm3cpp_gpio.h" + +namespace cm3cpp { + +namespace usart_dma { + +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 +}; + +/// Low level config for USART +struct LowLevelConfigUsart +{ + uint8_t usart_number; + gpio::Gpio::Pinout tx; + gpio::Gpio::Pinout rx; +}; + +/// Settings USART +struct Settings +{ + uint32_t baud_rate; + DataBits word_length; + StopBits stop_bits; + Parity parity; + Mode mode; + FlowControl flow_control; +}; + +/** + * Class Usart & Dma + */ +class UsartDma +{ + public: + /// Constructor + UsartDma(const LowLevelConfigUsart& usart_config, + const Settings& settings, + const dma::LowLevelConfig& dma_tx_config, + const dma::LowLevelConfig& dma_rx_config); + + /// Usart enable + void enable() const; + + /// Usart disable + void disable() const; + + /// Sending data to USART(not safe) + void write(uint8_t& data, uint16_t len); + + /* These classes must be public because + they can be accessed by interrupt handlers */ + class dma::Dma _dma_tx; ///< DMA for transmission + class dma::Dma _dma_rx; ///< DMA for receive + + protected: + UsartDma() = delete; /// Constructor default is delete + UsartDma(const UsartDma& a) = delete; /// Constructor copy is delete + UsartDma(const UsartDma&& a) = delete; /// Constructor move is delete + + UsartDma& operator=(const UsartDma&) = delete; /// Operator copy is delete + UsartDma& operator=(UsartDma&&) = delete; /// Operator move is delete + + private: + /// Set clock port GPIO + void port_config_clock_enable(uint32_t port) const; + + /// Config USART + void init_uasrt(const Settings& settings) const; + + uint32_t _usart; ///< Number USART +}; + +} // namespace usart_dma + +} // namespace cm3cpp |