1 // Copyright 2024 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 #pragma once
15 
16 #include "fsl_usart.h"
17 #include "pw_bytes/span.h"
18 #include "pw_clock_tree/clock_tree.h"
19 #include "pw_status/status.h"
20 #include "pw_stream/stream.h"
21 
22 namespace pw::stream {
23 
24 // Stream to output to a UART that is safe to use in an interrupt or fault
25 // handler context.
26 class InterruptSafeUartWriterMcuxpresso : public pw::stream::NonSeekableWriter {
27  public:
28   // Make sure constructor is constexpr. When used with `constinit`, this
29   // ensures that the object is fully constructed prior to static constructors
30   // having been executed.
31   // Doing so requires passing in the uart base pointer as a uintptr_t instead
32   // of USART_Type* to avoid needing a reinterpret_cast.
InterruptSafeUartWriterMcuxpresso(uintptr_t base,clock_name_t clock_name,unsigned int baudrate,pw::clock_tree::ClockTree & clock_tree,pw::clock_tree::Element & clock_tree_element)33   constexpr InterruptSafeUartWriterMcuxpresso(
34       uintptr_t base,
35       clock_name_t clock_name,
36       unsigned int baudrate,
37       pw::clock_tree::ClockTree& clock_tree,
38       pw::clock_tree::Element& clock_tree_element)
39       : base_(base),
40         baudrate_(baudrate),
41         element_controller_(&clock_tree, &clock_tree_element),
42         clock_name_(clock_name) {}
43 
InterruptSafeUartWriterMcuxpresso(uintptr_t base,clock_name_t clock_name,unsigned int baudrate)44   constexpr InterruptSafeUartWriterMcuxpresso(uintptr_t base,
45                                               clock_name_t clock_name,
46                                               unsigned int baudrate)
47       : base_(base), baudrate_(baudrate), clock_name_(clock_name) {}
48 
49   // Initialize uart to known good state. Can be used on UART that was already
50   // used by another driver to enable use in fault handler context.
51   pw::Status Enable();
52 
53  private:
54   pw::Status DoWrite(pw::ConstByteSpan data) override;
base()55   USART_Type* base() { return reinterpret_cast<USART_Type*>(base_); }
56 
57   const uintptr_t base_;
58   const unsigned int baudrate_;
59   pw::clock_tree::ElementController element_controller_;
60   const clock_name_t clock_name_;
61 };
62 
63 }  // namespace pw::stream
64