atmega_hal/
usart.rs

1//! USART
2//!
3//! # Example
4//!
5//! Complete example source code can be found in the repository:
6//! [`atmega2560-usart.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-usart.rs)
7//!
8//! *Note: [ufmt](https://crates.io/crates/ufmt/) is used instead of `core::fmt` because
9//! `core::fmt` code quickly grows too large for AVR platforms.*
10//!
11//! ```
12//! let dp = atmega_hal::Peripherals::take().unwrap();
13//! let pins = atmega_hal::pins!(dp);
14//!
15//! let mut serial = Usart::new(
16//!     dp.USART0,
17//!     pins.pe0,
18//!     pins.pe1.into_output(),
19//!     Baudrate::<crate::CoreClock>::new(57600),
20//! );
21//!
22//! ufmt::uwriteln!(&mut serial, "Hello from ATmega!").unwrap();
23//!
24//! loop {
25//!     // Read a byte from the serial connection
26//!     let b = nb::block!(serial.read()).unwrap();
27//!     // Answer
28//!     ufmt::uwriteln!(&mut serial, "Got {}!", b).unwrap();
29//! }
30//! ```
31
32#[allow(unused_imports)]
33use crate::port;
34pub use avr_hal_generic::usart::*;
35
36pub type Usart<USART, RX, TX, CLOCK> =
37    avr_hal_generic::usart::Usart<crate::Atmega, USART, RX, TX, CLOCK>;
38pub type UsartWriter<USART, RX, TX, CLOCK> =
39    avr_hal_generic::usart::UsartWriter<crate::Atmega, USART, RX, TX, CLOCK>;
40pub type UsartReader<USART, RX, TX, CLOCK> =
41    avr_hal_generic::usart::UsartReader<crate::Atmega, USART, RX, TX, CLOCK>;
42
43#[cfg(any(feature = "atmega16"))]
44pub type Usart0<CLOCK> = Usart<
45    crate::pac::USART,
46    port::Pin<port::mode::Input, port::PD0>,
47    port::Pin<port::mode::Output, port::PD1>,
48    CLOCK,
49>;
50#[cfg(any(
51    feature = "atmega88p",
52    feature = "atmega168",
53    feature = "atmega328p",
54    feature = "atmega328pb",
55    feature = "atmega1284p",
56    feature = "atmega164pa"
57))]
58pub type Usart0<CLOCK> = Usart<
59    crate::pac::USART0,
60    port::Pin<port::mode::Input, port::PD0>,
61    port::Pin<port::mode::Output, port::PD1>,
62    CLOCK,
63>;
64#[cfg(any(
65    feature = "atmega88p",
66    feature = "atmega168",
67    feature = "atmega328p",
68    feature = "atmega328pb",
69    feature = "atmega1284p",
70    feature = "atmega164pa"
71))]
72avr_hal_generic::impl_usart_traditional! {
73    hal: crate::Atmega,
74    peripheral: crate::pac::USART0,
75    register_suffix: 0,
76    rx: port::PD0,
77    tx: port::PD1,
78}
79
80#[cfg(feature = "atmega328pb")]
81pub type Usart1<CLOCK> = Usart<
82    crate::pac::USART1,
83    port::Pin<port::mode::Input, port::PB4>,
84    port::Pin<port::mode::Output, port::PB3>,
85    CLOCK,
86>;
87#[cfg(feature = "atmega328pb")]
88avr_hal_generic::impl_usart_traditional! {
89    hal: crate::Atmega,
90    peripheral: crate::pac::USART1,
91    register_suffix: 1,
92    rx: port::PB4,
93    tx: port::PB3,
94}
95
96#[cfg(any(
97    feature = "atmega32u4",
98    feature = "atmega128a",
99    feature = "atmega1280",
100    feature = "atmega2560",
101    feature = "atmega1284p",
102    feature = "atmega164pa"
103))]
104pub type Usart1<CLOCK> = Usart<
105    crate::pac::USART1,
106    port::Pin<port::mode::Input, port::PD2>,
107    port::Pin<port::mode::Output, port::PD3>,
108    CLOCK,
109>;
110#[cfg(any(
111    feature = "atmega32u4",
112    feature = "atmega1280",
113    feature = "atmega2560",
114    feature = "atmega1284p",
115    feature = "atmega164pa"
116))]
117avr_hal_generic::impl_usart_traditional! {
118    hal: crate::Atmega,
119    peripheral: crate::pac::USART1,
120    register_suffix: 1,
121    rx: port::PD2,
122    tx: port::PD3,
123}
124
125#[cfg(any(feature = "atmega128a", feature = "atmega1280", feature = "atmega2560"))]
126pub type Usart0<CLOCK> = Usart<
127    crate::pac::USART0,
128    port::Pin<port::mode::Input, port::PE0>,
129    port::Pin<port::mode::Output, port::PE1>,
130    CLOCK,
131>;
132#[cfg(any(feature = "atmega1280", feature = "atmega2560"))]
133avr_hal_generic::impl_usart_traditional! {
134    hal: crate::Atmega,
135    peripheral: crate::pac::USART0,
136    register_suffix: 0,
137    rx: port::PE0,
138    tx: port::PE1,
139}
140
141#[cfg(any(feature = "atmega1280", feature = "atmega2560"))]
142pub type Usart2<CLOCK> = Usart<
143    crate::pac::USART2,
144    port::Pin<port::mode::Input, port::PH0>,
145    port::Pin<port::mode::Output, port::PH1>,
146    CLOCK,
147>;
148#[cfg(any(feature = "atmega1280", feature = "atmega2560"))]
149avr_hal_generic::impl_usart_traditional! {
150    hal: crate::Atmega,
151    peripheral: crate::pac::USART2,
152    register_suffix: 2,
153    rx: port::PH0,
154    tx: port::PH1,
155}
156
157#[cfg(any(feature = "atmega1280", feature = "atmega2560"))]
158pub type Usart3<CLOCK> = Usart<
159    crate::pac::USART3,
160    port::Pin<port::mode::Input, port::PJ0>,
161    port::Pin<port::mode::Output, port::PJ1>,
162    CLOCK,
163>;
164#[cfg(any(feature = "atmega1280", feature = "atmega2560"))]
165avr_hal_generic::impl_usart_traditional! {
166    hal: crate::Atmega,
167    peripheral: crate::pac::USART3,
168    register_suffix: 3,
169    rx: port::PJ0,
170    tx: port::PJ1,
171}
172
173#[cfg(any(feature = "atmega8", feature = "atmega32a"))]
174pub type Usart0<CLOCK> = Usart<
175    crate::pac::USART,
176    port::Pin<port::mode::Input, port::PD0>,
177    port::Pin<port::mode::Output, port::PD1>,
178    CLOCK,
179>;
180
181// TODO: atmega8 USART is different from other atmegas
182// implemented so far. It uses the same register address
183// for UBRRH and UCSRC, the way to select which register
184// to write to, msb has to be 1 (for UCSRC)
185// or 0 (for UBRRH). Because of the same address,
186// these two are exposed as functions instead of
187// fields.
188#[cfg(any(feature = "atmega8", feature = "atmega32a"))]
189impl
190    crate::usart::UsartOps<
191        crate::Atmega,
192        crate::port::Pin<crate::port::mode::Input, port::PD0>,
193        crate::port::Pin<crate::port::mode::Output, port::PD1>,
194    > for crate::pac::USART
195{
196    fn raw_init<CLOCK>(&mut self, baudrate: crate::usart::Baudrate<CLOCK>) {
197        // msb of ubrrh has to be 0 to set ubrrh register. (see atmega8 datasheet)
198        let ubrrh: u8 = ((baudrate.ubrr >> 8) & 0x0F) as u8;
199        let ubrrl: u8 = (baudrate.ubrr & 0xFF) as u8;
200        self.ubrrh().write(|w| w.set(ubrrh));
201        self.ubrrl().write(|w| w.set(ubrrl));
202        self.ucsra().write(|w| w.u2x().bit(baudrate.u2x));
203
204        // Enable receiver and transmitter but leave interrupts disabled.
205        #[rustfmt::skip]
206        self.ucsrb().write(|w| w
207            .txen().set_bit()
208            .rxen().set_bit()
209        );
210
211        // Set frame format to 8n1 for now.  At some point, this should be made
212        // configurable, similar to what is done in other HALs.
213        #[rustfmt::skip]
214        self.ucsrc().write(|w| w
215            .ursel().set_bit() // sets the ucsrc instead of ubrrh (ubrrh and ucsrc share same location on ATmega8, see atmega8 datasheet)
216            .umsel().usart_async()
217            .ucsz().chr8()
218            .usbs().stop1()
219            .upm().disabled()
220        );
221    }
222
223    fn raw_deinit(&mut self) {
224        // Wait for any ongoing transfer to finish.
225        avr_hal_generic::nb::block!(self.raw_flush()).ok();
226        self.ucsrb().reset();
227    }
228
229    fn raw_flush(&mut self) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> {
230        if self.ucsra().read().udre().bit_is_clear() {
231            Err(avr_hal_generic::nb::Error::WouldBlock)
232        } else {
233            Ok(())
234        }
235    }
236
237    fn raw_write(
238        &mut self,
239        byte: u8,
240    ) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> {
241        // Call flush to make sure the data-register is empty
242        self.raw_flush()?;
243
244        self.udr().write(|w| w.set(byte));
245        Ok(())
246    }
247
248    fn raw_read(&mut self) -> avr_hal_generic::nb::Result<u8, core::convert::Infallible> {
249        if self.ucsra().read().rxc().bit_is_clear() {
250            return Err(avr_hal_generic::nb::Error::WouldBlock);
251        }
252
253        Ok(self.udr().read().bits())
254    }
255
256    fn raw_interrupt(&mut self, event: crate::usart::Event, state: bool) {
257        match event {
258            crate::usart::Event::RxComplete => {
259                self.ucsrb().modify(|_, w| w.rxcie().bit(state));
260            }
261            crate::usart::Event::TxComplete => {
262                self.ucsrb().modify(|_, w| w.txcie().bit(state));
263            }
264            crate::usart::Event::DataRegisterEmpty => {
265                self.ucsrb().modify(|_, w| w.udrie().bit(state));
266            }
267        }
268    }
269}
270
271// TODO: ATmega128A USART1 is also different from other atmegas
272// Mainly needed because ubrr1 is split in ubrr1h and ubrr1l
273#[cfg(any(feature = "atmega128a"))]
274impl
275    crate::usart::UsartOps<
276        crate::Atmega,
277        crate::port::Pin<crate::port::mode::Input, port::PD2>,
278        crate::port::Pin<crate::port::mode::Output, port::PD3>,
279    > for crate::pac::USART1
280{
281    fn raw_init<CLOCK>(&mut self, baudrate: crate::usart::Baudrate<CLOCK>) {
282        let ubrr1h: u8 = (baudrate.ubrr >> 8) as u8;
283        let ubrr1l: u8 = baudrate.ubrr as u8;
284        self.ubrr1h().write(|w| w.set(ubrr1h));
285        self.ubrr1l().write(|w| w.set(ubrr1l));
286        self.ucsr1a().write(|w| w.u2x1().bit(baudrate.u2x));
287
288        // Enable receiver and transmitter but leave interrupts disabled.
289        #[rustfmt::skip]
290        self.ucsr1b().write(|w| w
291            .txen1().set_bit()
292            .rxen1().set_bit()
293        );
294
295        // Set frame format to 8n1 for now.  At some point, this should be made
296        // configurable, similar to what is done in other HALs.
297        #[rustfmt::skip]
298        self.ucsr1c().write(|w| w
299            .umsel1().usart_async()
300            .ucsz1().chr8()
301            .usbs1().stop1()
302            .upm1().disabled()
303        );
304    }
305
306    fn raw_deinit(&mut self) {
307        // Wait for any ongoing transfer to finish.
308        avr_hal_generic::nb::block!(self.raw_flush()).ok();
309        self.ucsr1b().reset();
310    }
311
312    fn raw_flush(&mut self) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> {
313        if self.ucsr1a().read().udre1().bit_is_clear() {
314            Err(avr_hal_generic::nb::Error::WouldBlock)
315        } else {
316            Ok(())
317        }
318    }
319
320    fn raw_write(
321        &mut self,
322        byte: u8,
323    ) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> {
324        // Call flush to make sure the data-register is empty
325        self.raw_flush()?;
326
327        self.udr1().write(|w| w.set(byte));
328        Ok(())
329    }
330
331    fn raw_read(&mut self) -> avr_hal_generic::nb::Result<u8, core::convert::Infallible> {
332        if self.ucsr1a().read().rxc1().bit_is_clear() {
333            return Err(avr_hal_generic::nb::Error::WouldBlock);
334        }
335
336        Ok(self.udr1().read().bits())
337    }
338
339    fn raw_interrupt(&mut self, event: crate::usart::Event, state: bool) {
340        match event {
341            crate::usart::Event::RxComplete => {
342                self.ucsr1b().modify(|_, w| w.rxcie1().bit(state));
343            }
344            crate::usart::Event::TxComplete => {
345                self.ucsr1b().modify(|_, w| w.txcie1().bit(state));
346            }
347            crate::usart::Event::DataRegisterEmpty => {
348                self.ucsr1b().modify(|_, w| w.udrie1().bit(state));
349            }
350        }
351    }
352}
353
354// TODO: ATmega128A USART0 is also different from other atmegas
355// Mainly needed because ubrr1 is split in ubrr1h and ubrr1l
356// For USART0 they are not even close to eachother in memory
357#[cfg(any(feature = "atmega128a"))]
358impl
359    crate::usart::UsartOps<
360        crate::Atmega,
361        crate::port::Pin<crate::port::mode::Input, port::PE0>,
362        crate::port::Pin<crate::port::mode::Output, port::PE1>,
363    > for crate::pac::USART0
364{
365    fn raw_init<CLOCK>(&mut self, baudrate: crate::usart::Baudrate<CLOCK>) {
366        let ubrr0h: u8 = (baudrate.ubrr >> 8) as u8;
367        let ubrr0l: u8 = baudrate.ubrr as u8;
368        self.ubrr0h().write(|w| w.set(ubrr0h));
369        self.ubrr0l().write(|w| w.set(ubrr0l));
370        self.ucsr0a().write(|w| w.u2x0().bit(baudrate.u2x));
371
372        // Enable receiver and transmitter but leave interrupts disabled.
373        self.ucsr0b()
374            .write(|w| w.txen0().set_bit().rxen0().set_bit());
375
376        // Set frame format to 8n1 for now.  At some point, this should be made
377        // configurable, similar to what is done in other HALs.
378        #[rustfmt::skip]
379        self.ucsr0c().write(|w| w
380            .umsel0().usart_async()
381            .ucsz0().chr8()
382            .usbs0().stop1()
383            .upm0().disabled()
384        );
385    }
386
387    fn raw_deinit(&mut self) {
388        // Wait for any ongoing transfer to finish.
389        avr_hal_generic::nb::block!(self.raw_flush()).ok();
390        self.ucsr0b().reset();
391    }
392
393    fn raw_flush(&mut self) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> {
394        if self.ucsr0a().read().udre0().bit_is_clear() {
395            Err(avr_hal_generic::nb::Error::WouldBlock)
396        } else {
397            Ok(())
398        }
399    }
400
401    fn raw_write(
402        &mut self,
403        byte: u8,
404    ) -> avr_hal_generic::nb::Result<(), core::convert::Infallible> {
405        // Call flush to make sure the data-register is empty
406        self.raw_flush()?;
407
408        self.udr0().write(|w| w.set(byte));
409        Ok(())
410    }
411
412    fn raw_read(&mut self) -> avr_hal_generic::nb::Result<u8, core::convert::Infallible> {
413        if self.ucsr0a().read().rxc0().bit_is_clear() {
414            return Err(avr_hal_generic::nb::Error::WouldBlock);
415        }
416
417        Ok(self.udr0().read().bits())
418    }
419
420    fn raw_interrupt(&mut self, event: crate::usart::Event, state: bool) {
421        match event {
422            crate::usart::Event::RxComplete => {
423                self.ucsr0b().modify(|_, w| w.rxcie0().bit(state));
424            }
425            crate::usart::Event::TxComplete => {
426                self.ucsr0b().modify(|_, w| w.txcie0().bit(state));
427            }
428            crate::usart::Event::DataRegisterEmpty => {
429                self.ucsr0b().modify(|_, w| w.udrie0().bit(state));
430            }
431        }
432    }
433}