capsules_system/debug_writer/
uart_debug_writer.rs1use kernel::collections::queue::Queue;
8use kernel::collections::ring_buffer::RingBuffer;
9use kernel::debug::DebugWriter;
10use kernel::debug::IoWrite;
11use kernel::hil;
12use kernel::utilities::cells::TakeCell;
13use kernel::ErrorCode;
14
15pub struct UartDebugWriter {
19 uart: &'static dyn hil::uart::Transmit<'static>,
21 output_buffer: TakeCell<'static, [u8]>,
23 internal_buffer: TakeCell<'static, RingBuffer<'static, u8>>,
25}
26
27impl UartDebugWriter {
28 pub fn new(
29 uart: &'static dyn hil::uart::Transmit,
30 out_buffer: &'static mut [u8],
31 internal_buffer: &'static mut RingBuffer<'static, u8>,
32 ) -> UartDebugWriter {
33 UartDebugWriter {
34 uart,
35 output_buffer: TakeCell::new(out_buffer),
36 internal_buffer: TakeCell::new(internal_buffer),
37 }
38 }
39}
40
41impl DebugWriter for UartDebugWriter {
42 fn write(&self, bytes: &[u8], overflow_message: &[u8]) -> usize {
43 if let Some(ring_buffer) = self.internal_buffer.take() {
45 let available_len = ring_buffer
46 .available_len()
47 .saturating_sub(overflow_message.len());
48 let total_written = if available_len >= bytes.len() {
49 for &b in bytes {
50 ring_buffer.enqueue(b);
51 }
52 bytes.len()
53 } else {
54 for &b in &bytes[..available_len] {
57 ring_buffer.enqueue(b);
58 }
59 for &b in overflow_message {
60 ring_buffer.enqueue(b);
61 }
62 available_len + overflow_message.len()
63 };
64 self.internal_buffer.replace(ring_buffer);
66 total_written
67 } else {
68 bytes.len()
70 }
71 }
72
73 fn publish(&self) -> usize {
74 self.internal_buffer.map_or(0, |ring_buffer| {
77 if let Some(out_buffer) = self.output_buffer.take() {
78 let mut count = 0;
79
80 for dst in out_buffer.iter_mut() {
81 match ring_buffer.dequeue() {
82 Some(src) => {
83 *dst = src;
84 count += 1;
85 }
86 None => {
87 break;
88 }
89 }
90 }
91
92 if count != 0 {
93 if let Err((_err, buf)) = self.uart.transmit_buffer(out_buffer, count) {
95 self.output_buffer.put(Some(buf));
96 } else {
97 self.output_buffer.put(None);
98 }
99 }
100 count
101 } else {
102 0
103 }
104 })
105 }
106
107 fn flush(&self, writer: &mut dyn IoWrite) {
108 self.internal_buffer.map(|ring_buffer| {
109 writer.write_ring_buffer(ring_buffer);
110 });
111 }
112
113 fn available_len(&self) -> usize {
114 self.internal_buffer.map_or(0, |rb| rb.available_len())
115 }
116
117 fn to_write_len(&self) -> usize {
118 self.internal_buffer.map_or(0, |rb| rb.len())
119 }
120}
121
122impl hil::uart::TransmitClient for UartDebugWriter {
123 fn transmitted_buffer(
124 &self,
125 buffer: &'static mut [u8],
126 _tx_len: usize,
127 _rcode: Result<(), ErrorCode>,
128 ) {
129 self.output_buffer.replace(buffer);
131
132 if self.internal_buffer.map_or(false, |buf| buf.has_elements()) {
133 self.publish();
135 }
136 }
137 fn transmitted_word(&self, _rcode: Result<(), ErrorCode>) {}
138}
139
140impl IoWrite for UartDebugWriter {
141 fn write(&mut self, bytes: &[u8]) -> usize {
142 const FULL_MSG: &[u8] = b"\n*** DEBUG BUFFER FULL ***\n";
143 self.internal_buffer.map_or(0, |ring_buffer| {
144 let available_len_for_msg = ring_buffer.available_len().saturating_sub(FULL_MSG.len());
145
146 if available_len_for_msg >= bytes.len() {
147 for &b in bytes {
148 ring_buffer.enqueue(b);
149 }
150 bytes.len()
151 } else {
152 for &b in &bytes[..available_len_for_msg] {
153 ring_buffer.enqueue(b);
154 }
155 for &b in FULL_MSG {
158 ring_buffer.enqueue(b);
159 }
160 available_len_for_msg
161 }
162 })
163 }
164}