• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
99   GPIO_InitStruct.Pull = GPIO_NOPULL;
100 #if defined(STM32F0) || defined(STM32F1) || defined(STM32F3)
101   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
102 #else
103   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
104 #endif
105 #if !defined(STM32F1)
106   GPIO_InitStruct.Alternate = USART_GPIO_ALTERNATE_FUNC;
107 #endif  // !defined(STM32F1)
108   HAL_GPIO_Init(USART_GPIO_RX_PORT, &GPIO_InitStruct);
109 
110 #if defined(STM32F1)
111   USART_GPIO_REMAP();
112 #endif  // defined(STM32F1)
113 
114   uart.Instance = USART_INSTANCE;
115   uart.Init.BaudRate = 115200;
116   uart.Init.WordLength = UART_WORDLENGTH_8B;
117   uart.Init.StopBits = UART_STOPBITS_1;
118   uart.Init.Parity = UART_PARITY_NONE;
119   uart.Init.Mode = UART_MODE_TX_RX;
120   uart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
121   uart.Init.OverSampling = UART_OVERSAMPLING_16;
122   HAL_UART_Init(&uart);
123 }
124 
125 // This whole implementation is very inefficient because it uses the synchronous
126 // polling UART API and only reads / writes 1 byte at a time.
127 namespace pw::sys_io {
ReadByte(std::byte * dest)128 Status ReadByte(std::byte* dest) {
129   if (HAL_UART_Receive(
130           &uart, reinterpret_cast<uint8_t*>(dest), 1, HAL_MAX_DELAY) !=
131       HAL_OK) {
132     return Status::ResourceExhausted();
133   }
134   return OkStatus();
135 }
136 
TryReadByte(std::byte * dest)137 Status TryReadByte(std::byte* dest) { return Status::Unimplemented(); }
138 
WriteByte(std::byte b)139 Status WriteByte(std::byte b) {
140   if (HAL_UART_Transmit(
141           &uart, reinterpret_cast<uint8_t*>(&b), 1, HAL_MAX_DELAY) != HAL_OK) {
142     return Status::ResourceExhausted();
143   }
144   return OkStatus();
145 }
146 
147 // Writes a string using pw::sys_io, and add newline characters at the end.
WriteLine(std::string_view s)148 StatusWithSize WriteLine(std::string_view s) {
149   size_t chars_written = 0;
150   StatusWithSize result = WriteBytes(as_bytes(span(s)));
151   if (!result.ok()) {
152     return result;
153   }
154   chars_written += result.size();
155 
156   // Write trailing newline.
157   result = WriteBytes(as_bytes(span("\r\n", 2)));
158   chars_written += result.size();
159 
160   return StatusWithSize(OkStatus(), chars_written);
161 }
162 
163 }  // namespace pw::sys_io
164