diff --git a/Src/peripheral/uart/CMakeLists.txt b/Src/peripheral/uart/CMakeLists.txt new file mode 100644 index 0000000..c937d9a --- /dev/null +++ b/Src/peripheral/uart/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2023-2024 Dmitry Ponomarev +# Distributed under the terms of the GPL v3 license, available in the file LICENSE. + +# Include guard +if(PERIPHERAL_UART_CMAKE) + return() +endif() +set(PERIPHERAL_UART_CMAKE ${CMAKE_CURRENT_LIST_DIR}) + +if(NOT APP_PLATFORM) + message(SEND_ERROR "APP_PLATFORM is not specified or unsupported! Options: stm32f103, stm32g0b1, ubuntu.") +endif() + +if(APP_PLATFORM STREQUAL "stm32f103" OR APP_PLATFORM STREQUAL "stm32g0b1") + list(APPEND PERIPHERAL_SOURCES ${CMAKE_CURRENT_LIST_DIR}/uart_stm32.cpp) +elseif(APP_PLATFORM STREQUAL "ubuntu") + list(APPEND PERIPHERAL_SOURCES ${CMAKE_CURRENT_LIST_DIR}/uart_ubuntu.cpp) +else() + message(SEND_ERROR "APP_PLATFORM is unknown.") +endif() diff --git a/Src/peripheral/uart/uart.hpp b/Src/peripheral/uart/uart.hpp index ac4863b..1288a34 100644 --- a/Src/peripheral/uart/uart.hpp +++ b/Src/peripheral/uart/uart.hpp @@ -1,7 +1,50 @@ -// Copyright (C) 2023 Dmitry Ponomarev -// Distributed under the terms of the GPL v3 license, available in the file LICENSE. +/** + * This program is free software under the GNU General Public License v3. + * See for details. + * Author: Dmitry Ponomarev + */ -#ifndef SRC_PERIPHERY_UART_UART_HPP_ -#define SRC_PERIPHERY_UART_UART_HPP_ +#ifndef SRC_PERIPHERAL_UART_UART_HPP_ +#define SRC_PERIPHERAL_UART_UART_HPP_ -#endif // SRC_PERIPHERY_UART_UART_HPP_ +#include +#include + +namespace HAL { + +class UART { +public: + enum class Instance { + FIRST, + SECOND, + AMOUNT, + }; + + /** + * @brief Allocate resources, but not initialize yet + */ + UART(UART::Instance instance_) : instance(instance_) {} + + /** + * @brief After updating the baudrate, you typically want to reinialize the driver + */ + void set_baudrate(uint32_t rate); + + /** + * @brief RX DMA mode + * @return 0 on success, -1 on failure + */ + int8_t init_rx_dma(uint8_t buffer[], uint16_t size); + + /** + * @return a value in range [0, RX_DMA_BUFFER_SIZE - 1] + */ + size_t get_last_received_index(); + +private: + Instance instance; +}; + +} // namespace HAL + +#endif // SRC_PERIPHERAL_UART_UART_HPP_ diff --git a/Src/peripheral/uart/uart_stm32.cpp b/Src/peripheral/uart/uart_stm32.cpp new file mode 100644 index 0000000..4f872c3 --- /dev/null +++ b/Src/peripheral/uart/uart_stm32.cpp @@ -0,0 +1,89 @@ +/** + * This program is free software under the GNU General Public License v3. + * See for details. + * Author: Dmitry Ponomarev + */ + +#include "peripheral/uart/uart.hpp" +#include "main.h" + +extern UART_HandleTypeDef huart1; +#define UART_1_PTR &huart1 + +#if defined(SECOND_UART) + extern UART_HandleTypeDef huart2; + #define UART_2_PTR &huart2 +#else + #define UART_2_PTR NULL +#endif + +typedef enum { + NO_FLAGS = 0, + HALF_RECEIVED_FLAG, + FULL_RECEIVED_FLAG, + BOTH_FLAGS, +} UartRxStatus_t; + +typedef struct { + UART_HandleTypeDef* huart_ptr; + uint8_t* buffer; + uint16_t size; + UartRxStatus_t status; + void (*rx_callback)(); + uint32_t rx_counter; +} UartRxConfig_t; + +static UartRxConfig_t uart_rx[2] = { + {.huart_ptr = UART_1_PTR, .buffer = nullptr, .size = 0, .status = NO_FLAGS, .rx_callback = nullptr, .rx_counter = 0}, + {.huart_ptr = UART_2_PTR, .buffer = nullptr, .size = 0, .status = NO_FLAGS, .rx_callback = nullptr, .rx_counter = 0}, +}; + +namespace HAL { + +void UART::set_baudrate(uint32_t rate) { + if (instance == Instance::FIRST) { + huart1.Init.BaudRate = rate; + HAL_UART_Init(&huart1); + } else if (instance == Instance::SECOND) { +#if defined(SECOND_UART) + huart2.Init.BaudRate = rate; + HAL_HalfDuplex_Init(&huart2); +#endif + } +} + + +int8_t UART::init_rx_dma(uint8_t buffer[], uint16_t size) { + if (instance >= Instance::AMOUNT) { + return -1; + } + + auto& uart_rx_config = uart_rx[static_cast(instance)]; + + uart_rx_config.buffer = buffer; + uart_rx_config.size = size; + uart_rx_config.rx_counter = 0; + HAL_StatusTypeDef status = HAL_UART_Receive_DMA(uart_rx_config.huart_ptr, buffer, size); + return status == HAL_OK ? 0 : -1; +} + + +size_t UART:: get_last_received_index() { + if (instance >= Instance::AMOUNT) { + return 0; + } + + auto uart_rx_config = &uart_rx[static_cast(instance)]; + + if (uart_rx_config->huart_ptr == nullptr) { + return 0; + } + + uint16_t number_of_remaining_data_units = __HAL_DMA_GET_COUNTER(uart_rx_config->huart_ptr->hdmarx); + if (number_of_remaining_data_units == uart_rx_config->size) { + return uart_rx_config->size - 1; + } + return uart_rx_config->size - number_of_remaining_data_units - 1; +} + +} // namespace HAL diff --git a/Src/peripheral/uart/uart_ubuntu.cpp b/Src/peripheral/uart/uart_ubuntu.cpp new file mode 100644 index 0000000..45e9990 --- /dev/null +++ b/Src/peripheral/uart/uart_ubuntu.cpp @@ -0,0 +1,26 @@ +/** + * This program is free software under the GNU General Public License v3. + * See for details. + * Author: Dmitry Ponomarev + */ + +#include "peripheral/uart/uart.hpp" +#include "main.h" + +namespace HAL { + +void UART::set_baudrate(uint32_t rate) { + (void)rate; +} + +int8_t UART::init_rx_dma(uint8_t buffer[], uint16_t size) { + (void)buffer; + (void)size; + return 0; +} + +size_t UART:: get_last_received_index() { + return 0; +} + +} // namespace HAL diff --git a/Src/platform/stm32f103/CMakeLists.txt b/Src/platform/stm32f103/CMakeLists.txt index 466f5fe..f8f6c2b 100644 --- a/Src/platform/stm32f103/CMakeLists.txt +++ b/Src/platform/stm32f103/CMakeLists.txt @@ -4,6 +4,7 @@ set(EXECUTABLE ${PROJECT_NAME}.out) add_executable(${EXECUTABLE} ${APPLICATION_SOURCES} + ${PERIPHERAL_SOURCES} ${BUILD_SRC_DIR}/params.cpp ${ROOT_DIR}/Src/common/algorithms.cpp ${ROOT_DIR}/Src/common/logging.cpp diff --git a/Src/platform/stm32g0b1/CMakeLists.txt b/Src/platform/stm32g0b1/CMakeLists.txt index c6f5c3f..2aa54d8 100644 --- a/Src/platform/stm32g0b1/CMakeLists.txt +++ b/Src/platform/stm32g0b1/CMakeLists.txt @@ -9,6 +9,7 @@ cmake_path(GET SRC_DIR PARENT_PATH ROOT_DIR) set(EXECUTABLE ${PROJECT_NAME}.out) add_executable(${EXECUTABLE} ${APPLICATION_SOURCES} + ${PERIPHERAL_SOURCES} ${BUILD_SRC_DIR}/params.cpp ${ROOT_DIR}/Src/common/algorithms.cpp ${ROOT_DIR}/Src/common/logging.cpp diff --git a/Src/platform/ubuntu/CMakeLists.txt b/Src/platform/ubuntu/CMakeLists.txt index 2e8578e..8f32ca6 100644 --- a/Src/platform/ubuntu/CMakeLists.txt +++ b/Src/platform/ubuntu/CMakeLists.txt @@ -4,6 +4,7 @@ set(EXECUTABLE ${PROJECT_NAME}.out) add_executable(${EXECUTABLE} ${APPLICATION_SOURCES} + ${PERIPHERAL_SOURCES} ${BUILD_SRC_DIR}/params.cpp ${ROOT_DIR}/Src/common/algorithms.cpp ${ROOT_DIR}/Src/common/logging.cpp