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
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 pub fn new(usart: &'a UsartInner) -> Self {
90 Usart { inner: usart }
91 }
92
93 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 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 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 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 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 #[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);