embedded_c_sdk_bind_hal/
usart.rs

1use 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)]
11/// Config
12pub struct Config {
13    /// Baud rate
14    pub baudrate: u32,
15    /// Number of data bits
16    pub data_bits: UsartDataBits,
17    /// Number of stop bits
18    pub stop_bits: UsartStopBits,
19    /// Parity type
20    pub parity: UsartParity,
21    /// Hardware Flow Control
22    pub hw_flow: UsartHwFlowCtrl,
23    /// Tx Rx mode
24    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
59impl core::fmt::Display for Error {
60    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
61        match self {
62            Error::Code(code) => write!(f, "USART error code: {}", code),
63        }
64    }
65}
66
67impl core::error::Error for Error {}
68
69pub struct UsartInner {
70    id: UsartId,
71    rx_buf: RingBuffer<u8>,
72    #[cfg(feature = "embassy")]
73    rx_waker: AtomicWaker,
74}
75
76#[derive(Clone)]
77pub struct Usart<'a> {
78    inner: &'a UsartInner,
79}
80
81impl<'a> Usart<'a> {
82    /// Creates a new Usart instance wrapping around the given UsartInner reference.
83    ///
84    /// # Arguments
85    /// * `usart` - A reference to the inner Usart implementation.
86    ///
87    /// # Returns
88    /// * A new Usart instance.
89    pub fn new(usart: &'a UsartInner) -> Self {
90        Usart { inner: usart }
91    }
92
93    /// Initializes the USART with the provided configuration.
94    ///
95    /// # Arguments
96    /// * `config` - A reference to the configuration settings for the USART.
97    ///
98    /// # Returns
99    /// * An i32 indicating the status of the initialization.
100    pub fn init(&self, config: &Config) -> i32 {
101        ll_invoke_inner!(
102            INVOKE_ID_USART_INIT,
103            self.inner.id,
104            config.flags(),
105            config.baudrate
106        )
107    }
108
109    /// Sets the receive buffer for the USART.
110    ///
111    /// # Arguments
112    /// * `rx_buffer` - A mutable slice representing the receive buffer.
113    pub fn set_rx_buf(&self, rx_buffer: &mut [u8]) {
114        let len = rx_buffer.len();
115        unsafe { self.inner.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
116    }
117
118    /// Writes a buffer to the USART in a blocking manner.
119    ///
120    /// # Arguments
121    /// * `buf` - A slice containing the data to write.
122    ///
123    /// # Returns
124    /// * An i32 indicating the status of the write operation.
125    pub fn blocking_write(&self, buf: &[u8]) -> i32 {
126        ll_invoke_inner!(
127            INVOKE_ID_USART_WRITE,
128            self.inner.id,
129            buf.as_ptr(),
130            buf.len()
131        )
132    }
133
134    /// Reads into a buffer from the USART in a blocking manner.
135    ///
136    /// # Arguments
137    /// * `buffer` - A mutable slice representing the read buffer.
138    pub fn blocking_read(&self, buffer: &mut [u8]) {
139        let rx_buf = &self.inner.rx_buf;
140        let mut reader = unsafe { rx_buf.reader() };
141
142        for b in buffer {
143            while rx_buf.is_empty() {}
144            *b = reader.pop_one().unwrap_or(0);
145        }
146    }
147
148    /// Attempts to read a byte from the USART in a non-blocking manner.
149    ///
150    /// # Returns
151    /// * A Result containing the read byte or an error if the buffer is empty.
152    pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
153        let rx_buf = &self.inner.rx_buf;
154
155        if !rx_buf.is_empty() {
156            let mut reader = unsafe { rx_buf.reader() };
157            Ok(reader.pop_one().unwrap_or(0))
158        } else {
159            Err(nb::Error::WouldBlock)
160        }
161    }
162
163    /// An asynchronous read function for reading data into a provided buffer.
164    ///
165    /// # Arguments
166    /// * `buffer` - A mutable slice where the read bytes will be stored.
167    ///
168    /// # Returns
169    /// * Returns the number of bytes read as an `i32`, or `-1` if the buffer is empty,
170    ///   or `-2` if there was an error during the read operation.
171    #[cfg(feature = "embassy")]
172    async fn async_read(&self, buffer: &mut [u8]) -> i32 {
173        if buffer.is_empty() {
174            return -1;
175        }
176
177        let buffer_len = buffer.len();
178        let mut buffer_idx = 0;
179
180        let abort = core::future::poll_fn(move |cx| {
181            self.inner.rx_waker.register(cx.waker());
182
183            let mut reader = unsafe { self.inner.rx_buf.reader() };
184            while let Some(byte) = reader.pop_one() {
185                buffer[buffer_idx] = byte;
186                buffer_idx += 1;
187                if buffer_idx >= buffer_len {
188                    return core::task::Poll::Ready(Ok::<(), Error>(()));
189                }
190            }
191
192            return core::task::Poll::Pending;
193        });
194
195        let result = match abort.await {
196            Ok(_) => buffer_len as i32,
197            Err(_) => -2,
198        };
199
200        result
201    }
202}
203
204impl Drop for Usart<'_> {
205    fn drop(&mut self) {
206        ll_invoke_inner!(INVOKE_ID_USART_DEINIT, self.inner.id);
207    }
208}
209
210impl embedded_io::Error for Error {
211    fn kind(&self) -> embedded_io::ErrorKind {
212        embedded_io::ErrorKind::Other
213    }
214}
215
216impl embedded_io::ErrorType for Usart<'_> {
217    type Error = Error;
218}
219
220impl<'d> embedded_io::Read for Usart<'_> {
221    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
222        self.blocking_read(buf);
223        Ok(buf.len())
224    }
225}
226
227impl embedded_io::Write for Usart<'_> {
228    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
229        let result = self.blocking_write(buf);
230        if result == 0 {
231            return Ok(buf.len());
232        }
233        return Err(Error::Code(result));
234    }
235
236    fn flush(&mut self) -> Result<(), Self::Error> {
237        Ok(())
238    }
239}
240
241#[cfg(feature = "embassy")]
242impl embedded_io_async::Write for Usart<'_> {
243    async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
244        let result = self.blocking_write(buf);
245        if result == 0 {
246            return Ok(buf.len());
247        }
248        return Err(Error::Code(result));
249    }
250
251    async fn flush(&mut self) -> Result<(), Self::Error> {
252        Ok(())
253    }
254}
255
256#[cfg(feature = "embassy")]
257impl embedded_io_async::Read for Usart<'_> {
258    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
259        let result = self.async_read(buf).await;
260        if result > 0 {
261            return Ok(result as usize);
262        }
263        return Err(Error::Code(result));
264    }
265}
266
267impl embedded_hal_nb::serial::Error for Error {
268    fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
269        embedded_hal_nb::serial::ErrorKind::Other
270    }
271}
272impl<'d> embedded_hal_nb::serial::ErrorType for Usart<'_> {
273    type Error = Error;
274}
275
276impl<'d> embedded_hal_nb::serial::Read for Usart<'_> {
277    fn read(&mut self) -> nb::Result<u8, Self::Error> {
278        self.nb_read()
279    }
280}
281
282impl<'d> embedded_hal_nb::serial::Write for Usart<'_> {
283    fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
284        let result = self.blocking_write(&[char]);
285        if result == 0 {
286            return Ok(());
287        }
288        return Err(nb::Error::Other(Error::Code(result)));
289    }
290
291    fn flush(&mut self) -> nb::Result<(), Self::Error> {
292        Ok(())
293    }
294}
295
296#[cfg(feature = "_usart_impl")]
297macro_rules! impl_usart {
298    ($USART_id:ident) => {
299        pub static $USART_id: UsartInner = UsartInner {
300            id: UsartId::$USART_id,
301            rx_buf: RingBuffer::new(),
302            #[cfg(feature = "embassy")]
303            rx_waker: AtomicWaker::new(),
304        };
305
306        paste::paste! {
307            #[allow(non_snake_case)]
308            #[no_mangle]
309            unsafe extern "C" fn [<$USART_id _rx_hook_rs>] (val: u8) {
310                $USART_id.rx_buf.writer().push_one(val);
311                #[cfg(feature = "embassy")]
312                $USART_id.rx_waker.wake();
313            }
314        }
315    };
316}
317
318#[cfg(feature = "USART-0")]
319impl_usart!(USART0);
320
321#[cfg(feature = "USART-1")]
322impl_usart!(USART1);
323
324#[cfg(feature = "USART-2")]
325impl_usart!(USART2);
326
327#[cfg(feature = "USART-3")]
328impl_usart!(USART3);
329
330#[cfg(feature = "USART-4")]
331impl_usart!(USART4);
332
333#[cfg(feature = "USART-5")]
334impl_usart!(USART5);
335
336#[cfg(feature = "USART-6")]
337impl_usart!(USART6);
338
339#[cfg(feature = "USART-7")]
340impl_usart!(USART7);