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
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    /// Creates a new Usart instance wrapping around the given UsartInner reference.
73    ///
74    /// # Arguments
75    /// * `usart` - A reference to the inner Usart implementation.
76    ///
77    /// # Returns
78    /// * A new Usart instance.
79    pub fn new(usart: &'a UsartInner) -> Self {
80        Usart { inner: usart }
81    }
82
83    /// Initializes the USART with the provided configuration.
84    ///
85    /// # Arguments
86    /// * `config` - A reference to the configuration settings for the USART.
87    ///
88    /// # Returns
89    /// * An i32 indicating the status of the initialization.
90    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    /// Sets the receive buffer for the USART.
100    ///
101    /// # Arguments
102    /// * `rx_buffer` - A mutable slice representing the receive buffer.
103    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    /// Writes a buffer to the USART in a blocking manner.
109    ///
110    /// # Arguments
111    /// * `buf` - A slice containing the data to write.
112    ///
113    /// # Returns
114    /// * An i32 indicating the status of the write operation.
115    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    /// Reads into a buffer from the USART in a blocking manner.
125    ///
126    /// # Arguments
127    /// * `buffer` - A mutable slice representing the read buffer.
128    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    /// Attempts to read a byte from the USART in a non-blocking manner.
139    ///
140    /// # Returns
141    /// * A Result containing the read byte or an error if the buffer is empty.
142    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    /// An asynchronous read function for reading data into a provided buffer.
154    ///
155    /// # Arguments
156    /// * `buffer` - A mutable slice where the read bytes will be stored.
157    ///
158    /// # Returns
159    /// * Returns the number of bytes read as an `i32`, or `-1` if the buffer is empty,
160    ///   or `-2` if there was an error during the read operation.
161    #[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);