243 lines
7.3 KiB
C++
243 lines
7.3 KiB
C++
#pragma once
|
|
|
|
#include <stm32f1xx_hal.h>
|
|
|
|
#include <array>
|
|
#include <string_view>
|
|
|
|
#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 <uint16_t PinTX, uint16_t PinRX, uint32_t Port, uint32_t UsartBase,
|
|
UartMode M = UartMode::Interrupt, uint16_t Size = 1>
|
|
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<GPIO_TypeDef*>(port), &ua_tx);
|
|
HAL_GPIO_Init(reinterpret_cast<GPIO_TypeDef*>(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<uint32_t>(&s_UARTHandle.Instance->DR),
|
|
reinterpret_cast<uint32_t>(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_TypeDef*>(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<uint8_t*>(const_cast<char*>(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<uint8_t, Size> 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 <uint16_t PinTX, uint16_t PinRX, uint32_t Port, uint32_t UsartBase,
|
|
UartMode M, uint16_t Size>
|
|
DMA_HandleTypeDef uart_handler<PinTX, PinRX, Port, UsartBase, M,
|
|
Size>::s_DMAHandle = DMA_HandleTypeDef();
|
|
|
|
template <uint16_t PinTX, uint16_t PinRX, uint32_t Port, uint32_t UsartBase,
|
|
UartMode M, uint16_t Size>
|
|
UART_HandleTypeDef uart_handler<PinTX, PinRX, Port, UsartBase, M,
|
|
Size>::s_UARTHandle = UART_HandleTypeDef();
|
|
|
|
using uart_interface = uart_handler<UARTTX_PIN, UARTRX_PIN, UART_PORT,
|
|
USART1_BASE, UartMode::Interrupt>;
|
|
|
|
using gps_interface = uart_handler<UART2TX_PIN, UART2RX_PIN, UART2_PORT,
|
|
USART2_BASE, UartMode::DMA, 64>;
|