embedded_c_sdk_bind_hal/
usart.rs1use crate::common::atomic_ring_buffer::RingBuffer;
2use crate::ll_api::ll_cmd::*;
3#[cfg(feature = "embassy")]
4use embassy_sync::waitqueue::AtomicWaker;
5
6pub use crate::ll_api::{
7 UsartDataBits, UsartHwFlowCtrl, UsartId, UsartMode, UsartParity, UsartStopBits,
8};
9
10#[derive(Clone, Copy, PartialEq, Eq, Debug)]
11pub struct Config {
13 pub baudrate: u32,
15 pub data_bits: UsartDataBits,
17 pub stop_bits: UsartStopBits,
19 pub parity: UsartParity,
21 pub hw_flow: UsartHwFlowCtrl,
23 pub tx_rx_mode: UsartMode,
25}
26
27impl Default for Config {
28 fn default() -> Self {
29 Self {
30 baudrate: 115200,
31 data_bits: UsartDataBits::DataBits8,
32 stop_bits: UsartStopBits::STOP1,
33 parity: UsartParity::ParityNone,
34 hw_flow: UsartHwFlowCtrl::None,
35 tx_rx_mode: UsartMode::TxRx,
36 }
37 }
38}
39
40impl Config {
41 pub fn flags(&self) -> u32 {
42 let mut flags: u32;
43
44 flags = self.data_bits as u32;
45 flags |= self.stop_bits as u32;
46 flags |= self.parity as u32;
47 flags |= self.hw_flow as u32;
48 flags |= self.tx_rx_mode as u32;
49
50 flags
51 }
52}
53
54#[derive(Debug, PartialEq, Eq, Clone, Copy)]
55pub enum Error {
56 Code(i32),
57}
58
59pub struct UsartInner {
60 id: UsartId,
61 rx_buf: RingBuffer<u8>,
62 #[cfg(feature = "embassy")]
63 rx_waker: AtomicWaker,
64}
65
66#[derive(Clone)]
67pub struct Usart<'a> {
68 inner: &'a UsartInner,
69}
70
71impl<'a> Usart<'a> {
72 pub fn new(usart: &'a UsartInner) -> Self {
80 Usart { inner: usart }
81 }
82
83 pub fn init(&self, config: &Config) -> i32 {
91 ll_invoke_inner!(
92 INVOKE_ID_USART_INIT,
93 self.inner.id,
94 config.flags(),
95 config.baudrate
96 )
97 }
98
99 pub fn set_rx_buf(&self, rx_buffer: &mut [u8]) {
104 let len = rx_buffer.len();
105 unsafe { self.inner.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
106 }
107
108 pub fn blocking_write(&self, buf: &[u8]) -> i32 {
116 ll_invoke_inner!(
117 INVOKE_ID_USART_WRITE,
118 self.inner.id,
119 buf.as_ptr(),
120 buf.len()
121 )
122 }
123
124 pub fn blocking_read(&self, buffer: &mut [u8]) {
129 let rx_buf = &self.inner.rx_buf;
130 let mut reader = unsafe { rx_buf.reader() };
131
132 for b in buffer {
133 while rx_buf.is_empty() {}
134 *b = reader.pop_one().unwrap_or(0);
135 }
136 }
137
138 pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
143 let rx_buf = &self.inner.rx_buf;
144
145 if !rx_buf.is_empty() {
146 let mut reader = unsafe { rx_buf.reader() };
147 Ok(reader.pop_one().unwrap_or(0))
148 } else {
149 Err(nb::Error::WouldBlock)
150 }
151 }
152
153 #[cfg(feature = "embassy")]
162 async fn async_read(&self, buffer: &mut [u8]) -> i32 {
163 if buffer.is_empty() {
164 return -1;
165 }
166
167 let buffer_len = buffer.len();
168 let mut buffer_idx = 0;
169
170 let abort = core::future::poll_fn(move |cx| {
171 self.inner.rx_waker.register(cx.waker());
172
173 let mut reader = unsafe { self.inner.rx_buf.reader() };
174 while let Some(byte) = reader.pop_one() {
175 buffer[buffer_idx] = byte;
176 buffer_idx += 1;
177 if buffer_idx >= buffer_len {
178 return core::task::Poll::Ready(Ok::<(), Error>(()));
179 }
180 }
181
182 return core::task::Poll::Pending;
183 });
184
185 let result = match abort.await {
186 Ok(_) => buffer_len as i32,
187 Err(_) => -2,
188 };
189
190 result
191 }
192}
193
194impl Drop for Usart<'_> {
195 fn drop(&mut self) {
196 ll_invoke_inner!(INVOKE_ID_USART_DEINIT, self.inner.id);
197 }
198}
199
200impl embedded_io::Error for Error {
201 fn kind(&self) -> embedded_io::ErrorKind {
202 embedded_io::ErrorKind::Other
203 }
204}
205
206impl embedded_io::ErrorType for Usart<'_> {
207 type Error = Error;
208}
209
210impl<'d> embedded_io::Read for Usart<'_> {
211 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
212 self.blocking_read(buf);
213 Ok(buf.len())
214 }
215}
216
217impl embedded_io::Write for Usart<'_> {
218 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
219 let result = self.blocking_write(buf);
220 if result == 0 {
221 return Ok(buf.len());
222 }
223 return Err(Error::Code(result));
224 }
225
226 fn flush(&mut self) -> Result<(), Self::Error> {
227 Ok(())
228 }
229}
230
231#[cfg(feature = "embassy")]
232impl embedded_io_async::Write for Usart<'_> {
233 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
234 let result = self.blocking_write(buf);
235 if result == 0 {
236 return Ok(buf.len());
237 }
238 return Err(Error::Code(result));
239 }
240}
241
242#[cfg(feature = "embassy")]
243impl embedded_io_async::Read for Usart<'_> {
244 async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
245 let result = self.async_read(buf).await;
246 if result > 0 {
247 return Ok(result as usize);
248 }
249 return Err(Error::Code(result));
250 }
251}
252
253impl embedded_hal_nb::serial::Error for Error {
254 fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
255 embedded_hal_nb::serial::ErrorKind::Other
256 }
257}
258impl<'d> embedded_hal_nb::serial::ErrorType for Usart<'_> {
259 type Error = Error;
260}
261
262impl<'d> embedded_hal_nb::serial::Read for Usart<'_> {
263 fn read(&mut self) -> nb::Result<u8, Self::Error> {
264 self.nb_read()
265 }
266}
267
268impl<'d> embedded_hal_nb::serial::Write for Usart<'_> {
269 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
270 let result = self.blocking_write(&[char]);
271 if result == 0 {
272 return Ok(());
273 }
274 return Err(nb::Error::Other(Error::Code(result)));
275 }
276
277 fn flush(&mut self) -> nb::Result<(), Self::Error> {
278 Ok(())
279 }
280}
281
282#[cfg(feature = "_usart_impl")]
283macro_rules! impl_usart {
284 ($USART_id:ident) => {
285 pub static $USART_id: UsartInner = UsartInner {
286 id: UsartId::$USART_id,
287 rx_buf: RingBuffer::new(),
288 #[cfg(feature = "embassy")]
289 rx_waker: AtomicWaker::new(),
290 };
291
292 paste::paste! {
293 #[allow(non_snake_case)]
294 #[no_mangle]
295 #[inline]
296 unsafe extern "C" fn [<$USART_id _rx_hook_rs>] (val: u8) {
297 $USART_id.rx_buf.writer().push_one(val);
298 #[cfg(feature = "embassy")]
299 $USART_id.rx_waker.wake();
300 }
301 }
302 };
303}
304
305#[cfg(feature = "USART-0")]
306impl_usart!(USART0);
307
308#[cfg(feature = "USART-1")]
309impl_usart!(USART1);
310
311#[cfg(feature = "USART-2")]
312impl_usart!(USART2);
313
314#[cfg(feature = "USART-3")]
315impl_usart!(USART3);
316
317#[cfg(feature = "USART-4")]
318impl_usart!(USART4);
319
320#[cfg(feature = "USART-5")]
321impl_usart!(USART5);
322
323#[cfg(feature = "USART-6")]
324impl_usart!(USART6);
325
326#[cfg(feature = "USART-7")]
327impl_usart!(USART7);