Armando Montanez | 70045e2 | 2021-12-08 15:44:08 -0800 | [diff] [blame] | 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 | |
Armando Montanez | a398cd1 | 2021-12-13 10:57:41 -0800 | [diff] [blame] | 19 | #include "pw_preprocessor/concat.h" |
Armando Montanez | 70045e2 | 2021-12-08 15:44:08 -0800 | [diff] [blame] | 20 | #include "pw_status/status.h" |
Armando Montanez | a398cd1 | 2021-12-13 10:57:41 -0800 | [diff] [blame] | 21 | #include "pw_sys_io_stm32cube_private/config.h" |
Armando Montanez | 70045e2 | 2021-12-08 15:44:08 -0800 | [diff] [blame] | 22 | #include "stm32cube/stm32cube.h" |
| 23 | |
Armando Montanez | a398cd1 | 2021-12-13 10:57:41 -0800 | [diff] [blame] | 24 | // These macros remap config options to the various STM32Cube HAL macro names. |
Armando Montanez | 70045e2 | 2021-12-08 15:44:08 -0800 | [diff] [blame] | 25 | |
Armando Montanez | a398cd1 | 2021-12-13 10:57:41 -0800 | [diff] [blame] | 26 | // 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 Montanez | 70045e2 | 2021-12-08 15:44:08 -0800 | [diff] [blame] | 28 | |
Armando Montanez | a398cd1 | 2021-12-13 10:57:41 -0800 | [diff] [blame] | 29 | // 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 Montanez | 70045e2 | 2021-12-08 15:44:08 -0800 | [diff] [blame] | 42 | #define USART_GPIO_PORT_ENABLE \ |
Armando Montanez | a398cd1 | 2021-12-13 10:57:41 -0800 | [diff] [blame] | 43 | 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 Montanez | 70045e2 | 2021-12-08 15:44:08 -0800 | [diff] [blame] | 49 | |
| 50 | static UART_HandleTypeDef uart; |
| 51 | |
| 52 | extern "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. |
| 78 | namespace pw::sys_io { |
| 79 | Status 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 | |
| 88 | Status TryReadByte(std::byte* dest) { return Status::Unimplemented(); } |
| 89 | |
| 90 | Status 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. |
| 99 | StatusWithSize 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 |