#pragma once #include #include /* * small uart wrapper * assumes USART1 with default pins/port */ template struct uart_handler { static void enable_clocks() { __HAL_RCC_USART1_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); } 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); return result == HAL_OK; } static bool init() { enable_clocks(); init_gpio(); if (!enable_oscillators()) { return false; } return init_uart_handle(); } static HAL_StatusTypeDef write(const std::string_view& message, uint32_t timeout = HAL_MAX_DELAY) { constexpr std::string_view carriage_return{"\r\n"}; write(reinterpret_cast(const_cast(message.data())), message.size(), timeout); return write( reinterpret_cast(const_cast(carriage_return.data())), carriage_return.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; private: static constexpr auto pin_tx = PinTX; static constexpr auto pin_rx = PinRX; static constexpr auto port = Port; static constexpr auto usart_base = UsartBase; }; template UART_HandleTypeDef uart_handler::s_UARTHandle = UART_HandleTypeDef();