embassy
embassy copied to clipboard
Experiment: remove Instance generics.
This is an experiment of removing "peripheral instance" generics on driver structs. For example, uart is now Uart<'d, Blocking> instead of Uart<'d, UART1, Blocking>.
Everything is still checked at compile time as before (such as pin functions). The T generic is moved from the struct to the new methods, not removed entirely.
The main advantage is you can now write code that works with, e.g, both UART0 and UART1 without generics or macros.
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let config = uart::Config::default();
let uart0 = uart::Uart::new_with_rtscts_blocking(p.UART0, p.PIN_0, p.PIN_1, p.PIN_3, p.PIN_2, config);
let uart1 = uart::Uart::new_with_rtscts_blocking(p.UART1, p.PIN_4, p.PIN_5, p.PIN_7, p.PIN_6, config);
spawner.spawn(hello_task(uart0)).unwrap();
spawner.spawn(hello_task(uart1)).unwrap();
}
#[embassy_executor::task(pool_size = 2)]
async fn hello_task(mut uart: Uart<'static, Blocking>) {
uart.blocking_write("Hello World!\r\n".as_bytes()).unwrap();
loop {
uart.blocking_write("hello there!\r\n".as_bytes()).unwrap();
Timer::after(Duration::from_secs(1)).await;
}
}
code size comparison with default build settings:
text data bss dec hex filename
14656 48 1552 16256 3f80 old, uart0
14720 48 1568 16336 3fd0 new, uart0: +64 bytes
16312 48 1616 17976 4638 old, uart0+uart1 (copypaste)
15032 48 1656 16736 4160 new, uart0+uart1: -1280 bytes
As expected, it's a big win when using multiple instances because the code doesn't get duplicated
With build-std, panic-immediate-abort, lto=fat, opt-level=z:
text data bss dec hex filename
4356 48 1544 5948 173c old, uart0
4376 48 1568 5992 1768 new, uart0: +20 bytes
4652 48 1608 6308 18a4 old, uart0+uart1 (copypaste)
4792 48 1656 6496 1960 new, uart0+uart1: +140 bytes
new loses, not sure why. Probably the inliner just changing its mind. It doesn't reproduce with a more complex example:
text data bss dec hex filename
5532 48 2592 8172 1fec uart_old_1
5520 48 2632 8200 2008 uart_new_1: -12 bytes
6644 48 3704 10396 289c uart_old_2
6016 48 3784 9848 2678 uart_new_2: -628 bytes
so i'm pretty confident that in general new/old is a ~tie when using just 1 instance, and new wins when using more than 1.