xref: /aosp_15_r20/external/pigweed/pw_sys_io_stm32cube/sys_io.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // 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 
19 #include "pw_preprocessor/concat.h"
20 #include "pw_status/status.h"
21 #include "pw_sys_io_stm32cube_private/config.h"
22 #include "stm32cube/stm32cube.h"
23 
24 // These macros remap config options to the various STM32Cube HAL macro names.
25 
26 // USART_INSTANCE defined to USARTn, where n is the USART peripheral index.
27 #define USART_INSTANCE \
28   PW_CONCAT(PW_SYS_IO_STM32CUBE_USART_PREFIX, PW_SYS_IO_STM32CUBE_USART_NUM)
29 
30 // USART_GPIO_ALTERNATE_FUNC defined to GPIO_AFm_USARTn, where m is the
31 // alternate function index and n is the USART peripheral index.
32 #define USART_GPIO_ALTERNATE_FUNC             \
33   PW_CONCAT(GPIO_AF,                          \
34             PW_SYS_IO_STM32CUBE_GPIO_AF,      \
35             _,                                \
36             PW_SYS_IO_STM32CUBE_USART_PREFIX, \
37             PW_SYS_IO_STM32CUBE_USART_NUM)
38 
39 // USART_GPIO_REMAP defined to __HAL_AFIO_REMAP_USARTn_val,
40 // where n is the USART peripheral index and val is ENABLE or DISABLE.
41 // It only applies to the stm32f1xx family.
42 #define USART_GPIO_REMAP                      \
43   PW_CONCAT(__HAL_AFIO_REMAP_,                \
44             PW_SYS_IO_STM32CUBE_USART_PREFIX, \
45             PW_SYS_IO_STM32CUBE_USART_NUM,    \
46             _,                                \
47             PW_SYS_IO_STM32CUBE_GPIO_REMAP)
48 
49 // USART_GPIO_PORT defined to GPIOx, where x is the GPIO port letter that the
50 // TX/RX pins are on.
51 #define USART_GPIO_TX_PORT PW_CONCAT(GPIO, PW_SYS_IO_STM32CUBE_GPIO_TX_PORT)
52 #define USART_GPIO_RX_PORT PW_CONCAT(GPIO, PW_SYS_IO_STM32CUBE_GPIO_RX_PORT)
53 #define USART_GPIO_TX_PIN PW_CONCAT(GPIO_PIN_, PW_SYS_IO_STM32CUBE_GPIO_TX_PIN)
54 #define USART_GPIO_RX_PIN PW_CONCAT(GPIO_PIN_, PW_SYS_IO_STM32CUBE_GPIO_RX_PIN)
55 
56 // USART_GPIO_PORT_ENABLE defined to __HAL_RCC_GPIOx_CLK_ENABLE, where x is the
57 // GPIO port letter that the TX/RX pins are on.
58 #define USART_GPIO_TX_PORT_ENABLE \
59   PW_CONCAT(__HAL_RCC_GPIO, PW_SYS_IO_STM32CUBE_GPIO_TX_PORT, _CLK_ENABLE)
60 
61 #define USART_GPIO_RX_PORT_ENABLE \
62   PW_CONCAT(__HAL_RCC_GPIO, PW_SYS_IO_STM32CUBE_GPIO_RX_PORT, _CLK_ENABLE)
63 
64 // USART_ENABLE defined to __HAL_RCC_USARTn_CLK_ENABLE, where n is the USART
65 // peripheral index.
66 #define USART_ENABLE                          \
67   PW_CONCAT(__HAL_RCC_,                       \
68             PW_SYS_IO_STM32CUBE_USART_PREFIX, \
69             PW_SYS_IO_STM32CUBE_USART_NUM,    \
70             _CLK_ENABLE)
71 
72 static UART_HandleTypeDef uart;
73 
pw_sys_io_Init()74 extern "C" void pw_sys_io_Init() {
75   GPIO_InitTypeDef GPIO_InitStruct = {};
76 
77   USART_ENABLE();
78   USART_GPIO_TX_PORT_ENABLE();
79   USART_GPIO_RX_PORT_ENABLE();
80 #if defined(STM32F1)
81   __HAL_RCC_AFIO_CLK_ENABLE();
82 #endif  // defined(STM32F1)
83 
84   GPIO_InitStruct.Pin = USART_GPIO_TX_PIN;
85   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
86   GPIO_InitStruct.Pull = GPIO_NOPULL;
87 #if defined(STM32F0) || defined(STM32F1) || defined(STM32F3)
88   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
89 #else
90   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
91 #endif
92 #if !defined(STM32F1)
93   GPIO_InitStruct.Alternate = USART_GPIO_ALTERNATE_FUNC;
94 #endif  // !defined(STM32F1)
95   HAL_GPIO_Init(USART_GPIO_TX_PORT, &GPIO_InitStruct);
96 
97   GPIO_InitStruct.Pin = USART_GPIO_RX_PIN;
98 #if defined(STM32F1)
99   GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT;
100 #else
101   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
102 #endif
103   GPIO_InitStruct.Pull = GPIO_NOPULL;
104 #if defined(STM32F0) || defined(STM32F1) || defined(STM32F3)
105   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
106 #else
107   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
108 #endif
109 #if !defined(STM32F1)
110   GPIO_InitStruct.Alternate = USART_GPIO_ALTERNATE_FUNC;
111 #endif  // !defined(STM32F1)
112   HAL_GPIO_Init(USART_GPIO_RX_PORT, &GPIO_InitStruct);
113 
114 #if defined(STM32F1)
115   USART_GPIO_REMAP();
116 #endif  // defined(STM32F1)
117 
118   uart.Instance = USART_INSTANCE;
119   uart.Init.BaudRate = 115200;
120   uart.Init.WordLength = UART_WORDLENGTH_8B;
121   uart.Init.StopBits = UART_STOPBITS_1;
122   uart.Init.Parity = UART_PARITY_NONE;
123   uart.Init.Mode = UART_MODE_TX_RX;
124   uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
125   uart.Init.OverSampling = UART_OVERSAMPLING_16;
126   HAL_UART_Init(&uart);
127 }
128 
129 // This whole implementation is very inefficient because it uses the synchronous
130 // polling UART API and only reads / writes 1 byte at a time.
131 namespace pw::sys_io {
ReadByte(std::byte * dest)132 Status ReadByte(std::byte* dest) {
133   if (HAL_UART_Receive(
134           &uart, reinterpret_cast<uint8_t*>(dest), 1, HAL_MAX_DELAY) !=
135       HAL_OK) {
136     return Status::ResourceExhausted();
137   }
138   return OkStatus();
139 }
140 
TryReadByte(std::byte * dest)141 Status TryReadByte(std::byte* dest) { return Status::Unimplemented(); }
142 
WriteByte(std::byte b)143 Status WriteByte(std::byte b) {
144   if (HAL_UART_Transmit(
145           &uart, reinterpret_cast<uint8_t*>(&b), 1, HAL_MAX_DELAY) != HAL_OK) {
146     return Status::ResourceExhausted();
147   }
148   return OkStatus();
149 }
150 
151 // Writes a string using pw::sys_io, and add newline characters at the end.
WriteLine(std::string_view s)152 StatusWithSize WriteLine(std::string_view s) {
153   size_t chars_written = 0;
154   StatusWithSize result = WriteBytes(as_bytes(span(s)));
155   if (!result.ok()) {
156     return result;
157   }
158   chars_written += result.size();
159 
160   // Write trailing newline.
161   result = WriteBytes(as_bytes(span("\r\n", 2)));
162   chars_written += result.size();
163 
164   return StatusWithSize(OkStatus(), chars_written);
165 }
166 
167 }  // namespace pw::sys_io
168