embassy icon indicating copy to clipboard operation
embassy copied to clipboard

Experiment: remove Instance generics.

Open Dirbaio opened this issue 3 years ago • 1 comments

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;
    }
}

Dirbaio avatar Sep 27 '22 20:09 Dirbaio

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.

Dirbaio avatar Sep 27 '22 21:09 Dirbaio