#pragma once #include #include #include #include "stm32f1xx_it.h" // USART 1 constexpr auto UART_PORT = GPIOA_BASE; #define UARTPORT GPIOA #define UARTTX_PIN GPIO_PIN_9 #define UARTRX_PIN GPIO_PIN_10 // USART 2 constexpr auto UART2_PORT = GPIOA_BASE; #define UART2PORT GPIOA #define UART2TX_PIN GPIO_PIN_2 #define UART2RX_PIN GPIO_PIN_3 /* * small uart wrapper * assumes USART1 with default pins/port */ enum class UartMode : uint8_t { Blocking = 0, Interrupt, DMA, }; template struct uart_handler { static void enable_clocks() { if constexpr (UsartBase == USART1_BASE) { __HAL_RCC_USART1_CLK_ENABLE(); } else if constexpr (UsartBase == USART2_BASE) { __HAL_RCC_USART2_CLK_ENABLE(); } __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_AFIO_CLK_ENABLE(); } static void init_gpio() { GPIO_InitTypeDef ua_tx; GPIO_InitTypeDef ua_rx; ua_tx.Pin = pin_tx; ua_tx.Mode = GPIO_MODE_AF_PP; ua_tx.Speed = GPIO_SPEED_HIGH; ua_rx.Pin = pin_rx; ua_rx.Mode = GPIO_MODE_INPUT; ua_rx.Speed = GPIO_SPEED_HIGH; HAL_GPIO_Init(reinterpret_cast(port), &ua_tx); HAL_GPIO_Init(reinterpret_cast(port), &ua_rx); // if constexpr (UsartBase == USART1_BASE) { // /* USART1 interrupt Init */ // HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(USART1_IRQn); // } ///* USART2 interrupt Init */ // HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(USART2_IRQn); } static void init_mode() { if (M == UartMode::Blocking) { return; // nothing to od } if constexpr (M == UartMode::Interrupt) { constexpr auto GlobalInterrupt = [](auto Base) { if (Base == USART1_BASE) { return USART1_IRQn; } if (Base == USART2_BASE) { return USART2_IRQn; } }(UsartBase); HAL_NVIC_SetPriority(GlobalInterrupt, 0, 0); HAL_NVIC_EnableIRQ(GlobalInterrupt); HAL_UART_Receive_IT(&s_UARTHandle, &rx_buff, rx_buff_size); return; } if constexpr (M == UartMode::DMA) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_AFIO_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); /* System interrupt init*/ /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled */ __HAL_AFIO_REMAP_SWJ_NOJTAG(); /* DMA interrupt init */ /* DMA1_Channel6_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel6_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Channel6_IRQn); s_DMAHandle.Instance = DMA1_Channel6; s_DMAHandle.Init.Direction = DMA_PERIPH_TO_MEMORY; s_DMAHandle.Init.PeriphInc = DMA_PINC_DISABLE; s_DMAHandle.Init.MemInc = DMA_MINC_ENABLE; s_DMAHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; s_DMAHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; s_DMAHandle.Init.Mode = DMA_NORMAL; s_DMAHandle.Init.Priority = DMA_PRIORITY_LOW; write("TRY DMA INIT"); if (HAL_DMA_Init(&s_DMAHandle) != HAL_OK) { write("FAILED"); // Error_Handler(); } __HAL_LINKDMA(&s_UARTHandle, hdmarx, s_DMAHandle); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); HAL_DMA_Start_IT( &s_DMAHandle, reinterpret_cast(&s_UARTHandle.Instance->DR), reinterpret_cast(new_rx_buf.data()), new_rx_buf.size()); HAL_UARTEx_ReceiveToIdle_DMA(&s_UARTHandle, new_rx_buf.data(), new_rx_buf.size()); __HAL_DMA_DISABLE_IT(&s_DMAHandle, DMA_IT_HT); } } static bool enable_oscillators() { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { return false; } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { return false; } return true; } static bool init_uart_handle() { s_UARTHandle.Instance = reinterpret_cast(usart_base); s_UARTHandle.Init.BaudRate = 9600; s_UARTHandle.Init.WordLength = UART_WORDLENGTH_8B; s_UARTHandle.Init.StopBits = UART_STOPBITS_1; s_UARTHandle.Init.Parity = UART_PARITY_NONE; s_UARTHandle.Init.Mode = UART_MODE_TX_RX; s_UARTHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; auto result = HAL_UART_Init(&s_UARTHandle); if (result != HAL_OK) { return false; } return result == HAL_OK; } static bool init() { enable_clocks(); init_gpio(); if (!enable_oscillators()) { return false; } auto result = init_uart_handle(); init_mode(); return result; } static HAL_StatusTypeDef write(const std::string_view& message, uint32_t timeout = HAL_MAX_DELAY) { return write(reinterpret_cast(const_cast(message.data())), message.size(), timeout); } static HAL_StatusTypeDef write(uint8_t* buf, uint16_t size, uint32_t timeout = HAL_MAX_DELAY) { return HAL_UART_Transmit(&s_UARTHandle, buf, size, timeout); } static UART_HandleTypeDef s_UARTHandle; static DMA_HandleTypeDef s_DMAHandle; static uint8_t* get_buf() { return &rx_buff; } static const uint8_t* get_buf_c() { return &rx_buff; } static std::array new_rx_buf; private: static constexpr auto pin_tx = PinTX; static constexpr auto pin_rx = PinRX; static constexpr auto port = Port; static constexpr auto usart_base = UsartBase; static constexpr size_t rx_buff_size = 1; static uint8_t rx_buff; }; template DMA_HandleTypeDef uart_handler::s_DMAHandle = DMA_HandleTypeDef(); template UART_HandleTypeDef uart_handler::s_UARTHandle = UART_HandleTypeDef(); using uart_interface = uart_handler; using gps_interface = uart_handler;