xref: /aosp_15_r20/external/pigweed/pw_sys_io_ambiq_sdk/sys_io.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 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 "am_bsp.h"
20 #include "am_mcu_apollo.h"
21 #include "pw_preprocessor/compiler.h"
22 
23 namespace {
24 void* hal_uart_handle{};
25 }  // namespace
26 
pw_sys_io_Init()27 PW_EXTERN_C void pw_sys_io_Init() {
28   // Use baud rate of 115200 (8N1).
29   static constexpr am_hal_uart_config_t kUartConfig = {
30       .ui32BaudRate = 115200,
31       .eDataBits = AM_HAL_UART_DATA_BITS_8,
32       .eParity = AM_HAL_UART_PARITY_NONE,
33       .eStopBits = AM_HAL_UART_ONE_STOP_BIT,
34       .eFlowControl = AM_HAL_UART_FLOW_CTRL_NONE,
35       .eTXFifoLevel = AM_HAL_UART_FIFO_LEVEL_16,
36       .eRXFifoLevel = AM_HAL_UART_FIFO_LEVEL_16,
37   };
38 
39   // Initialize the UART peripheral.
40   am_hal_uart_initialize(AM_BSP_UART_PRINT_INST, &hal_uart_handle);
41 
42   // Change the power state of the UART peripheral.
43   am_hal_uart_power_control(hal_uart_handle, AM_HAL_SYSCTRL_WAKE, false);
44 
45   // Configure UART (baudrate etc.).
46   am_hal_uart_configure(hal_uart_handle, &kUartConfig);
47 
48   // Enable the UART TX and RX GPIO's.
49   am_hal_gpio_pinconfig(AM_BSP_GPIO_COM_UART_TX, g_AM_BSP_GPIO_COM_UART_TX);
50   am_hal_gpio_pinconfig(AM_BSP_GPIO_COM_UART_RX, g_AM_BSP_GPIO_COM_UART_RX);
51 }
52 
53 namespace pw::sys_io {
54 
55 // Wait for a byte to read on UART0. This blocks until a byte is read. This is
56 // extremely inefficient as it requires the target to burn CPU cycles polling to
57 // see if a byte is ready yet.
ReadByte(std::byte * dest)58 Status ReadByte(std::byte* dest) {
59   while (true) {
60     if (TryReadByte(dest).ok()) {
61       return OkStatus();
62     }
63   }
64 }
65 
TryReadByte(std::byte * dest)66 Status TryReadByte(std::byte* dest) {
67   am_hal_uart_transfer_t transaction{};
68   uint32_t bytes_read{};
69 
70   // Configure UART transaction for the read operation.
71   transaction.eType = AM_HAL_UART_BLOCKING_READ;
72   transaction.pui8Data = reinterpret_cast<uint8_t*>(dest);
73   transaction.ui32NumBytes = 1;
74   transaction.ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER;
75   transaction.pui32BytesTransferred = &bytes_read;
76 
77   // Do read data over UART.
78   if (am_hal_uart_transfer(hal_uart_handle, &transaction) !=
79       AM_HAL_STATUS_SUCCESS) {
80     return Status::ResourceExhausted();
81   }
82 
83   if (bytes_read != 1u) {
84     return Status::DataLoss();
85   }
86 
87   return OkStatus();
88 }
89 
WriteByte(std::byte b)90 Status WriteByte(std::byte b) {
91   am_hal_uart_transfer_t transaction{};
92   uint32_t chars_written{};
93 
94   // Configure UART transaction for the write operation.
95   transaction.eType = AM_HAL_UART_BLOCKING_WRITE;
96   transaction.pui8Data =
97       const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&b));
98   transaction.ui32NumBytes = 1;
99   transaction.ui32TimeoutMs = AM_HAL_UART_WAIT_FOREVER;
100   transaction.pui32BytesTransferred = &chars_written;
101 
102   // Do write data over UART.
103   if (am_hal_uart_transfer(hal_uart_handle, &transaction) !=
104       AM_HAL_STATUS_SUCCESS) {
105     return Status::ResourceExhausted();
106   }
107 
108   if (chars_written != 1) {
109     return Status::DataLoss();
110   }
111 
112   return OkStatus();
113 }
114 
115 // Writes a string using pw::sys_io, and add newline characters at the end.
WriteLine(std::string_view s)116 StatusWithSize WriteLine(std::string_view s) {
117   StatusWithSize result = WriteBytes(as_bytes(span(s)));
118   if (!result.ok()) {
119     return result;
120   }
121 
122   size_t chars_written = result.size();
123   if (chars_written != s.size()) {
124     return StatusWithSize::DataLoss(chars_written);
125   }
126 
127   // Write trailing newline.
128   result = WriteBytes(as_bytes(span("\r\n", 2)));
129   chars_written += result.size();
130 
131   if (result.size() != 2) {
132     return StatusWithSize::DataLoss(chars_written);
133   }
134 
135   return StatusWithSize(chars_written);
136 }
137 
138 }  // namespace pw::sys_io
139