blob: e9e6d7e73bcbda6214ceeeb25ab59388d067a1d5 [file] [log] [blame]
Armando Montanez70045e22021-12-08 15:44:08 -08001// Copyright 2021 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#include "pw_sys_io/sys_io.h"
16
17#include <cinttypes>
18
Armando Montaneza398cd12021-12-13 10:57:41 -080019#include "pw_preprocessor/concat.h"
Armando Montanez70045e22021-12-08 15:44:08 -080020#include "pw_status/status.h"
Armando Montaneza398cd12021-12-13 10:57:41 -080021#include "pw_sys_io_stm32cube_private/config.h"
Armando Montanez70045e22021-12-08 15:44:08 -080022#include "stm32cube/stm32cube.h"
23
Armando Montaneza398cd12021-12-13 10:57:41 -080024// These macros remap config options to the various STM32Cube HAL macro names.
Armando Montanez70045e22021-12-08 15:44:08 -080025
Armando Montaneza398cd12021-12-13 10:57:41 -080026// USART_INSTANCE defined to USARTn, where n is the USART peripheral index.
27#define USART_INSTANCE PW_CONCAT(USART, PW_SYS_IO_STM32CUBE_USART_NUM)
Armando Montanez70045e22021-12-08 15:44:08 -080028
Armando Montaneza398cd12021-12-13 10:57:41 -080029// USART_GPIO_ALTERNATE_FUNC defined to GPIO_AF7_USARTn, where n is the USART
30// peripheral index.
31#define USART_GPIO_ALTERNATE_FUNC \
32 PW_CONCAT(GPIO_AF7_USART, PW_SYS_IO_STM32CUBE_USART_NUM)
33
34// USART_GPIO_PORT defined to GPIOx, where x is the GPIO port letter that the
35// TX/RX pins are on.
36#define USART_GPIO_PORT PW_CONCAT(GPIO, PW_SYS_IO_STM32CUBE_GPIO_PORT)
37#define USART_GPIO_TX_PIN PW_CONCAT(GPIO_PIN_, PW_SYS_IO_STM32CUBE_GPIO_TX_PIN)
38#define USART_GPIO_RX_PIN PW_CONCAT(GPIO_PIN_, PW_SYS_IO_STM32CUBE_GPIO_RX_PIN)
39
40// USART_GPIO_PORT_ENABLE defined to __HAL_RCC_GPIOx_CLK_ENABLE, where x is the
41// GPIO port letter that the TX/RX pins are on.
Armando Montanez70045e22021-12-08 15:44:08 -080042#define USART_GPIO_PORT_ENABLE \
Armando Montaneza398cd12021-12-13 10:57:41 -080043 PW_CONCAT(__HAL_RCC_GPIO, PW_SYS_IO_STM32CUBE_GPIO_PORT, _CLK_ENABLE)
44
45// USART_ENABLE defined to __HAL_RCC_USARTn_CLK_ENABLE, where n is the USART
46// peripheral index.
47#define USART_ENABLE \
48 PW_CONCAT(__HAL_RCC_USART, PW_SYS_IO_STM32CUBE_USART_NUM, _CLK_ENABLE)
Armando Montanez70045e22021-12-08 15:44:08 -080049
50static UART_HandleTypeDef uart;
51
52extern "C" void pw_sys_io_Init() {
53 GPIO_InitTypeDef GPIO_InitStruct = {};
54
55 USART_ENABLE();
56 USART_GPIO_PORT_ENABLE();
57
58 GPIO_InitStruct.Pin = USART_GPIO_TX_PIN | USART_GPIO_RX_PIN;
59 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
60 GPIO_InitStruct.Pull = GPIO_NOPULL;
61 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
62 GPIO_InitStruct.Alternate = USART_GPIO_ALTERNATE_FUNC;
63 HAL_GPIO_Init(USART_GPIO_PORT, &GPIO_InitStruct);
64
65 uart.Instance = USART_INSTANCE;
66 uart.Init.BaudRate = 115200;
67 uart.Init.WordLength = UART_WORDLENGTH_8B;
68 uart.Init.StopBits = UART_STOPBITS_1;
69 uart.Init.Parity = UART_PARITY_NONE;
70 uart.Init.Mode = UART_MODE_TX_RX;
71 uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
72 uart.Init.OverSampling = UART_OVERSAMPLING_16;
73 HAL_UART_Init(&uart);
74}
75
76// This whole implementation is very inefficient because it uses the synchronous
77// polling UART API and only reads / writes 1 byte at a time.
78namespace pw::sys_io {
79Status ReadByte(std::byte* dest) {
80 if (HAL_UART_Receive(
81 &uart, reinterpret_cast<uint8_t*>(dest), 1, HAL_MAX_DELAY) !=
82 HAL_OK) {
83 return Status::ResourceExhausted();
84 }
85 return OkStatus();
86}
87
88Status TryReadByte(std::byte* dest) { return Status::Unimplemented(); }
89
90Status WriteByte(std::byte b) {
91 if (HAL_UART_Transmit(
92 &uart, reinterpret_cast<uint8_t*>(&b), 1, HAL_MAX_DELAY) != HAL_OK) {
93 return Status::ResourceExhausted();
94 }
95 return OkStatus();
96}
97
98// Writes a string using pw::sys_io, and add newline characters at the end.
99StatusWithSize WriteLine(const std::string_view& s) {
100 size_t chars_written = 0;
101 StatusWithSize result = WriteBytes(std::as_bytes(std::span(s)));
102 if (!result.ok()) {
103 return result;
104 }
105 chars_written += result.size();
106
107 // Write trailing newline.
108 result = WriteBytes(std::as_bytes(std::span("\r\n", 2)));
109 chars_written += result.size();
110
111 return StatusWithSize(OkStatus(), chars_written);
112}
113
114} // namespace pw::sys_io