GithubHelp home page GithubHelp logo

embassy-rs / embassy Goto Github PK

View Code? Open in Web Editor NEW
4.4K 4.4K 583.0 15.07 MB

Modern embedded framework, using Rust and async.

Home Page: https://embassy.dev

License: Apache License 2.0

Rust 98.93% Shell 0.87% Python 0.19% RPC 0.01%
async drivers embedded executor hal rust

embassy's People

Contributors

alexmoon avatar barnabywalters avatar bobmcwhirter avatar bors[bot] avatar bugadani avatar caleb-garrett avatar cbjamo avatar chemicstry avatar danbev avatar diondokter avatar dirbaio avatar eziopan avatar grantm11235 avatar huntc avatar jacobrosenthal avatar jamesmunns avatar julidi avatar kalkyl avatar kbleeke avatar lulf avatar mathiaskoch avatar matoushybl avatar pennae avatar rmja avatar sgoll avatar thalesfragoso avatar theunkn0wn1 avatar timokroeger avatar vdorst avatar xoviat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

embassy's Issues

share interrupt between tasks

every task would allocate a "waitqueue node" in their own future, you link them together as a linked list
with Pin you're guaranteed that these nodes don't move and that Drop is called, so it's sound
it's how futures-intrusive works internally
but it'd need lots and lots of unsafe
and care so codesize doesn't blow up :S
futures-intrusive is a bit heavy on code size, I think it can be improved somewhat

Implement blocking APIs

We want embassy drivers to be usable with both the async embassy-traits and the blocking embedded_hal::blocking traits.

Reasons:

  1. compatibility with the existing ecosystem of drivers.
  2. Better code size / cpu usage if you know you're doing a very short operation. For example, for an SPI Ethernet chip you could do async for packet transfers, but blocking for the very short register accesses.

OwnedInterrupt: mark set_handler/remove_handler as unsafe

Since introducing the ctx pointer, the handler is now two words, so setting it can race with the interrupt firing! On race it's possible for the new handler to be called with the old ctx pointer or viceversa.

Since this is very low level, I'd rather have the user enable/disable the interrupt if this is a concern, instead of doing a critical section in set_handler/remove_handler.

Remove rand()

The current Rand trait is completely out of scope, it's not even async.

Maybe in the future we can have an async Rand trait, but for now the demand doesn't seem to be there.

Which Mutes should I choose ?

static UART: Once<Mutex<Uarte<pac::UARTE0>>> = Once::new();

#[thread::task(pool_size = 20)]
async fn serial_send(buf: Vec<u8>) {
    let uart = UART.get().unwrap();
    let _err = uart.lock().send(&buf).await;
}
#[thread::task]
async fn serial_recv() {
    let mut buf = [0; 1];
    loop {
        let uart = UART.get().unwrap();
        let _err = uart.lock().receive(&mut buf).await;
    }
}

fn send(buf: &[u8]) {
    thread::spawn(serial_send(Vec::from(buf)));
}

pub fn start(uart: Uarte<pac::UARTE0>) {
    let _err = UART.call_once(|| Mutex::new(uart));

    send(&[1,2,3,4,5]);
    thread::spawn(serial_recv());
}

Document the methods on AsyncBufReadExt

Document the methods on AsyncBufReadExt

In particular I need a method that will fill the provided buffer with as much data is available but not wait for further data to arrive.

Rename I2C trait

Currently the trait is called 'read'; it should be more descriptive.

UB in Portal

It's using the UnsafeCell to get multiple &muts to the content simultaneously

Revisit `interrupt` package naming.

Maybe rename OwnedInterrupt -> Interrupt and FOOInterrupt -> FOO.

This would make embassy's interrupt mod incompatible with the PACs', but much more clearer. Right now all the "old-style" enum interrupt and the "embassy-style" owned interrupt stuff is mixed.

Add stm32?

Would it be acceptable if I created a new embassy-stm32f4xx folder and submitted a pull request?

embassy-nrf: New Event/Task types

So I've just tried the new updates and found no way to link up timer compare events to PPI, as ppi::Event is not implemented for the timer events and Event::from_reg is private.
Will Event::from_reg eventually become public or be implemented for the rest of the peripherals?
For now I will just make from_reg public and use it like in BufferedUarte, but I might be missing something

`rtc_async` example does not work on nrf52810

    Finished dev [optimized + debuginfo] target(s) in 1.27s
     Running `probe-run --chip nRF52810_xxAA C:\Users\XXX\embassy\target\thumbv7em-none-eabi\debug\rtc_async`
  (HOST) INFO  flashing program (19.04 KiB)
  (HOST) INFO  success!
────────────────────────────────────────────────────────────────────────────────
0.000000 INFO  Hello World!
└─ rtc_async::__cortex_m_rt_main @ src\bin\rtc_async.rs:41
0.000001 INFO  tick
└─ rtc_async::run2::task::{{closure}} @ src\bin\rtc_async.rs:30
0.000002 INFO  BIG INFREQUENT TICK
└─ rtc_async::run1::task::{{closure}} @ src\bin\rtc_async.rs:22

Stuck at this forever.

The async_raw example runs as expected, so the bug might not actually be in the RTC code.

executor: audit Send-safety

I'm not 100% sure whether the executor is safe wrt Send/non-Send futures.

Ideally there should be two APIs, one to spawn non-Send futures, and another one to spawn Send futures. Only the second one should be usable cross-thread (where in embedded context "thread" means "interrupt priority level)

[feature requiest] low power mode for peripherals

It would be convenient if peripherals supported going into low power mode (disconnecting GPIO pins, disabling SPI, etc.). I'm not sure if this should live in embassy or in user code. It can be a bit fiddly to write because you need a way to represent the different states, which gets complicated with the typed state you get on Rust (a disconnected pin is not the same type as an input or output pin, even though in reality it is zero-sized and doesn't even exist in machine code).

remove qei trait and impl

I originally thought that the qei trait would be useful, but I now think that polling with delays is a better approach. The main problem with the qei trait is that you can lose time (ticks) when using the interrupt approach. I will leave this open for a few days and remove it if no one objects.

Type-erased AnyInterrupt type

Similar to AnyPin from the nrf and rp HALs. You'd call .degrade() on a typed interrupt and get an AnyInterrupt.

Together with AnyPin and type-erased AnyUarte/AnySpim/etc peripherals you could reduce code duplication due to generics.

Some examples fail to run with the latest executor timer improvements

Affected examples:

  • gpiote_port
  • gpiote
  • qspi
  • uart
   Compiling embassy-examples v0.1.0 (C:\Users\user\Desktop\code\rust\embassy\examples)
    Finished dev [optimized + debuginfo] target(s) in 0.75s
     Running `probe-run --chip nRF52840_xxAA --defmt C:\Users\user\Desktop\code\rust\embassy\target\thumbv7em-none-eabihf\debug\gpiote_port`
  (HOST) INFO  flashing program (18.48 KiB)
  (HOST) INFO  success!
────────────────────────────────────────────────────────────────────────────────
0.000000 INFO  Hello World!
└─ gpiote_port::__cortex_m_rt_main @ src\bin\gpiote_port.rs:51
0.000001 ERROR panicked at 'No clock set'
└─ embassy::time::now @ C:\Users\user\Desktop\code\rust\embassy\embassy\src\time\mod.rs:22

Add #[embassy::main] attribute

To ease adoption of async and reduce boilerplate for simple projects, we could have a macro that allows you to simply have an async main. No need for creating executor, setting up the clock and alarm, the macro does it for you with some sensible, opinionated config. tokio and async-std have similar macros.

This'd be optional of course, you'd still be able to set up executor(s) manually.

The main issue is how to do clock setup in a way that works with all boards (especially on stm32s) or how to let the user specify it. It needs to be done before executor start.

#[embassy::main]
async fn main(spawner: Spawner) {
    // here you can do async stuff directly.

    // if you need more tasks you can spawn 
    spawner.spawn(foo()).unwrap()
}

Would be good to audit interrupt logic

I had some trouble with an earlier version of embassy because I hit a data race in the way that the interrupts was set to trigger. That issues is fixed now, AFAICT when I look at the code, but I think someone should do a detailed audit of the logic at some point. It's the kind of thing where you can't just wait for bug reports, because if it does cause problems they will be very rare and difficult to reproduce, since they rely on timing.

This isn't a criticism of the code, which looks good, but just a note that an audit would be worthwhile sometime in the future when the codebase has stabilized a bit.

Add Signal::new_from_interrupt

Pattern: accepts an OwnedInterrupt and sets the handler to one of many static handlers defined in the signal module. Poll_wait stores waker.clone() in a static array (using a malloc/free scheme to keep track of available handlers/wakers). Interrupt handler disables interrupt and wakes waker.

This scheme is resistant to memory moves, and solves headaches from dealing with interrupts.

OwnedInterrupt: add compiler fences

many OwnedInterrupt methods should have compiler fences, so for example enabling/disabling is guaranteed to be ordered vs other memory accesses.

restructure interrupt handling - discussion

Currently, interrupts are structured such that they are owned by one trait. However, it may be the case that interrupts are used by multiple traits independently, and the current project structure exposes interrupts to the user. I propose the following changes:

  • A single struct, similar to ownedinterrupt, that allows traits to add and remove handlers to the interrupt. The first add_handler would enable the interrupt and calling remove_handlers would disable it.
  • a new method that would simply wake_by_ref the waker on an interrupt, similar to what I have in my pull request with the waker_interrupt macro.

Thoughts?

nrf-softdevice faults when used with embassy_nrf::Gpiote

As the title says, when using embassy_nrf::Gpiote together with nrf-softdevice, the nrf-softdevice (S140 7.2.0)
an explicit panic occurs, in this case with

0.001253 ERROR panicked at 'fault_handler 4097 191576 0'

I still have to investigate this further (and throw together a minimal example), but I assume it has something to do with NVIC access or critical sections.

If someone could point out where to look further it would be much appreciated

Edit:
I created a button handler task which awaits a pin using GPIOTE port interrupt, then polls the desired pin every 5ms (timer provided by embassy::time) to debounce

Dropping a BufferedUarte after writing to it hangs.

In the following example "after write" is printed but "after drop" is never reached.
All the read methods also block forever but while that could be an issue on my end, blocking forever on drop seems very unexpected so I raised this issue.

#[embassy::main]
async fn main(_spawner: Spawner) {
    let mut p = unsafe { Peripherals::steal() };
    let mut irq = interrupt::take!(UARTE0_UART0);

    loop {
        let mut tx_buffer = [0u8; 4096];
        let mut rx_buffer = [0u8; 4096];
        {
            let mut config = uarte::Config::default();
            config.parity = uarte::Parity::EXCLUDED;
            config.baudrate = uarte::Baudrate::BAUD115200;

            let uart = unsafe {
                BufferedUarte::new(
                    &mut p.UARTE0,
                    &mut p.TIMER0,
                    &mut p.PPI_CH0,
                    &mut p.PPI_CH1,
                    &mut irq,
                    &mut p.P1_05,
                    &mut p.P1_04,
                    &mut p.P1_07,
                    &mut p.P1_06,
                    config,
                    &mut rx_buffer,
                    &mut tx_buffer,
                )
            };
            info!("uart initialized!");
            pin_mut!(uart);
            Timer::after(Duration::from_millis(1000)).await;
            info!("before write");
            uart.write_all(b"AT\r\n").await.unwrap();
            info!("after write");
        }
        info!("after drop");
    }
}

Document "leak-safety" in driver futures

Many drivers have new be unsafe to have the user pledge that they won't leak any futures, so we can use DMA with borrowed slices which is much more ergonomic than embedded_dma.

We should add an in-depth explanation on why that is and what are the implications somewhere (readme, main module) and link to it from all the affected news.

using embassy without rtc?

I finally got around to testing on my device, but received a panic:

panic_halt::panic@0x0800b392 (~\.cargo\registry\src\github.com-1ecc6299db9ec823\panic-halt-0.2.0\src\lib.rs:33)
core::panicking::panic_fmt@0x0800a99e (Unknown Source:92)
embassy::time::now@0x0800a390 (~\.cargo\git\checkouts\embassy-52086c5c548bb7b2\c6cf9b8\embassy\src\time\mod.rs:22)
embassy::time::instant::Instant::now@0x08009ab6 (~\.cargo\git\checkouts\embassy-52086c5c548bb7b2\c6cf9b8\embassy\src\time\instant.rs:19)
embassy::executor::Executor::run@0x08009d66 (~\.cargo\git\checkouts\embassy-52086c5c548bb7b2\c6cf9b8\embassy\src\executor\mod.rs:217)
rust_grinder::__cortex_m_rt_main@0x08002292 (~\workspace\tproject\src\main.rs:111)
rust_grinder::__cortex_m_rt_main_trampoline@0x08002212 (~\workspace\tproject\src\main.rs:102)

Is it possible to use embassy without rtc? The Qspi example does not have it enabled. stm32 has it, but I haven't used it yet, so it would take me some time to enable.

SPI transfers for stm32

I would like to port my (ls7366)[https://github.com/theunkn0wn1/LS7366_rust/] driver to embassy, but SPI is not implemented for STM32.

Uart4 on stm32f446 emits garbage.

MCU: stm32f446 on a nucleo board.

I attached a logic analyzer as well as a FTDI to the TX/RX of Uart4 to observe the results of the test.

the software being run is here

Expected result:

Logic analyzer / remote end receives bytes [0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x1, 0xf0, ...]

Actual result:

image

In [19]: con.read_all()
Out[19]: b'\x00\xff\x00\xff\x00\x00\xff\x00\xff\x06\x00\x00\xff\x00\xff\x00\xff\x00\xff\x00\x00\xff\x00\xff\x00\xff\x00\xff\x00\x00\xff\x00\x00\x00\xff\x00\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff'

support i2c for stm32g0x1

I'm working on an embedded project that has an stm32g0x1 microcontroller which needs to act as an i2c peripheral (aka slave) on one bus and an i2c controller (aka master) on another bus. It also needs to be a peripheral on a SPI bus.

Do you have any thoughts on how this could / should be implemented in Embassy? Assuming I end up using Embassy, I'm happy to do most of the implementation of this myself, but any guidance would be greatly appreciated.

I2C traits

I'm extensively using I2C in my project together with embassy and it would be nice to have an I2C interface trait to implement for a particular chip (stm32wb55 in my case).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.