Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/thirdpin/libopencm3_cpp_extensions.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvanOrfanidi <i.orfanidi@thirdpin.io>2019-05-31 17:37:45 +0300
committerIvanOrfanidi <i.orfanidi@thirdpin.io>2019-06-03 11:09:21 +0300
commitf5ec1056a15d90bee6965dc43426212dd19c2117 (patch)
tree304becd3eedf269e1fa43192b20262aa306b4aaa
parente5bbcc02fa5cef76e1a4dea13f8aae125f12a95a (diff)
Added USART and DMA drivers
-rw-r--r--CMakeLists.txt3
-rw-r--r--cm3cpp_dma.cpp107
-rw-r--r--cm3cpp_dma.hpp155
-rw-r--r--cm3cpp_usart_dma.cpp202
-rw-r--r--cm3cpp_usart_dma.hpp129
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