Git Product home page Git Product logo

nrf-softdevice's People

Contributors

a-gavin avatar adinack avatar albertskog avatar alexmoon avatar alimoal avatar andreas-move-innovation avatar bobmcwhirter avatar chrysn avatar danbev avatar dirbaio avatar dzervas avatar dzfranklin avatar fnafnio avatar haobogu avatar huntc avatar jacobrosenthal avatar kext avatar lonesometraveler avatar lulf avatar matoushybl avatar mehmetalianil avatar plaes avatar rise0chen avatar tarfu avatar taylor-shift avatar timokroeger avatar univa avatar ve5li avatar xgroleau avatar yandrik 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

nrf-softdevice's Issues

Macro to make writing GATT clients easier?

Here's an example of how GATT clients are written now: https://github.com/akiles/nrf-softdevice/blob/7567bffb617135a68138762e2a7ca2793a26fe75/example/src/bin/ble_bas_central.rs#L32-L73

For every characteristic, we have to:

  • Add field to hold the handle for the value, the cccd (if needed)
  • Add code on discovered_characteristic that matches the UUID and fills the fields if matches, and checks all necessary operations are supported (read/write/notification/etc)
  • Add code on discovery_complete that checks all needed UUID are filled.
  • Add methods to read/write/etc the characteristic (not yet done in above code).

That's all boring boilerplate which could be generated with a proc macro.

#[gatt_client::Client(uuid=180F)]
struct BatteryServiceClient {
    #[characteristic(uuid=2A19, read, notify)]
    battery_level: u8,
}

which would generate an impl of gatt_client::Client like the above, and methods to use the characteristics such as:

async fn battery_level_read(&self) -> Result<u8, gatt_client::ReadError>

For receiving notifications/indications user would have to implement their own function such as on_battery_level_notification on the struct.

Suggestions and comments on the proposed API welcome :)

gatt: Panics when receiving writes with bad length

How to reproduce:

  • Create a writable char of type u8.
  • Connect to the device with nRF Connect, write an empty value to it.

I have no idea why this happens.

there's this vlen attr (for "variable length") https://github.com/embassy-rs/nrf-softdevice/blob/master/nrf-softdevice/src/ble/gatt_server.rs#L21
it's false if MIN_LEN==MAX_LEN: https://github.com/embassy-rs/nrf-softdevice/blob/master/nrf-softdevice-macro/src/lib.rs#L246
which is the case for something like u8 https://github.com/embassy-rs/nrf-softdevice/blob/master/nrf-softdevice/src/ble/gatt_traits.rs#L39-L40

So either I'm misunderstanding what vlen does, or there's some bug somewhere (in our code or in the softdevice??)

Examples do not compile

Compilation of the examples fails with:

error[E0599]: no method named `dewrap` found for enum `core::result::Result<(), SpawnError>` in the current scope
   --> examples/src/bin/ble_bas_central.rs:163:42
 note: the method `dewrap` exists but the following trait bounds were not satisfied:
            `SpawnError: Format`
            which is required by `core::result::Result<(), SpawnError>: example_common::Dewrap<()>`

I assume that the derived implementations for defmt are not being generated.

Failing to build on OS X

Very excited to use this project and help where I can!

I'm finding the getting started a bit rough. Out of the box, and noting that I'm using OS X:

% ./test-build.sh 
+ cd examples
+ cargo build --target thumbv7em-none-eabihf --features cortex-m-rtic --bins
  Downloaded rtic-syntax v0.4.0
  Downloaded cortex-m-rtic v0.5.5
  Downloaded cortex-m-rtic-macros v0.5.2
  Downloaded rtic-core v0.3.0
  Downloaded 4 crates (149.3 KB) in 1.05s
   Compiling stable_deref_trait v1.2.0
   Compiling vcell v0.1.2
   Compiling bitfield v0.13.2
   Compiling r0 v0.2.2
   Compiling futures-core v0.3.8
   Compiling futures-sink v0.3.8
   Compiling scopeguard v1.1.0
   Compiling autocfg v1.0.1
   Compiling futures-task v0.3.8
   Compiling pin-utils v0.1.0
   Compiling nb v1.0.0
   Compiling futures-io v0.3.8
   Compiling hashbrown v0.9.1
   Compiling void v1.0.2
   Compiling anyfmt v0.1.0 (https://github.com/akiles/embassy#2e062f56)
   Compiling rand_core v0.5.1
error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: unknown debugging option: `trap-unreachable`

error: could not compile `scopeguard`

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed

I also note that CI is failing presently at commit 41f00393ddd5607c415ecc3d1862703c85411820. However, previous working CI commit also fails for me. Something to do with my OS X environment?

Radio timeslot API

This would be mainly useful to run concurrently Bluetooth with other protocols (such as ESB for example).

This is not a very high priority because its use is quite niche. If you do find them useful for your project, please do reach out!

L2CAP

This is not a very high priority because it seems L2CAP CoC channels are not very widely used. If you do find them useful for your project, please do reach out!

Rtic example will panic when taking peripherals

The current examples use pub fn take_peripherals() -> (nrf_softdevice::Peripherals, Peripherals) in example_common.rs but this crashes with an error when using rtic.

error: `Unwrap of a None option value`
└─ firmware::common::take_peripherals @ src/example_common.rs:40

The fix implies to put them in Resources

    struct Resources {
        timer: Timer<TIMER1, Periodic>,
        sdp: Option<nrf_softdevice::Peripherals>,
    }
   // init
      let sdp = nrf_softdevice::Peripherals {
            AAR: cx.device.AAR,
            ACL: cx.device.ACL,
            CCM: cx.device.CCM,
            CLOCK: cx.device.CLOCK,
            ECB: cx.device.ECB,
            EGU1: cx.device.EGU1,
            EGU2: cx.device.EGU2,
            EGU5: cx.device.EGU5,
            MWU: cx.device.MWU,
            NVMC: cx.device.NVMC,
            POWER: cx.device.POWER,
            RADIO: cx.device.RADIO,
            RNG: cx.device.RNG,
            RTC0: cx.device.RTC0,
            SWI1: cx.device.SWI1,
            SWI2: cx.device.SWI2,
            SWI5: cx.device.SWI5,
            TEMP: cx.device.TEMP,
            TIMER0: cx.device.TIMER0,
        };
        let sdp = Some(sdp);

        init::LateResources {
            sdp,
            timer,
        }
// when creating soft device
        let sd = Softdevice::enable(cx.resources.sdp.take().unwrap(), &config);

Disallow declaring IRQ handlers for reserved interrupts?

Currently this builds fine in user code

#[interrupt]
fn RADIO() {
    info!("RADIO triggered!")
}

but will not work since RADIO is a softdevice-reserved interrupt. I think it does work before enabling the softdevice, and after enabling it'll just never fire (the softdevice never forwards that irq to the application).

Not sure if this should be somehow prevented from compiling (if that's even possible).

ATT MTU negotiation

Similarly to #5, the ATT MTU must be negotiated using sd_ble_gattc_exchange_mtu_request. I think it's only necessary if we're the GATT client.

Better Config struct

The current Config struct is very ugly because it uses the original C structs.

  • Very unergonomic, especially when they have bitfields.
  • All fields are Options, which is
  • Users override a field all-or-nothing. If they want to change a single setting of a group they can't, they have to specify Some and then the whole struct.

The reason for the Options this is to allow users to not set them, in which case we don't even call sd_ble_cfg_set, and the softdevice uses a defaul configuration. Unfortunately the softdevice headers don't document the default of many settings :(

Ideally it'd be a pure-Rust struct with much better ergonomics and safety, implementing Default::default with defaults matching the softdevice's. We'd call sd_ble_cfg_set for absolutely every setting even if they're defaults.

Investigate PPI safety

The softdevice has a bunch of sd_ppi_* functions, which makes me think we can't freely use PPI when softdevice is enabled. This may conflict with PPI usage in nrf-hal or other libs.

At the very least we should document it.

Question: How to safely configure SoftDevice peripherals before giving up ownership?

Hi,

First off, thanks for all this great work on embassy and nrf-softdevice!

Sorry if this is a noob question.

I am trying to combine this crate with the usb-device. I have both working separately.

For the USB stuff I use enable_ext_hfosc to configure the clock.

Something like this:

let periph = Peripherals::take().unwrap();
let clocks = nrf52840_hal::Clocks::new(periph.CLOCK);
let clocks = clocks.enable_ext_hfosc();

As Softdevice::Peripherals requires ownership of CLOCK I don't see a way to do this other than manually setting the register.

Temperature sensor

Should be easy, just calling sd_temp_get.

Maybe check if there's a HAL trait out there and implement that.

Better logs on softdevice faults

Current logs don't give any actionable info on how to deal with the error, so people get stuck: #45 https://github.com/akiles/embassy/issues/42

For NRF_FAULT_ID_SD_ASSERT:

  • suggest checking interrupts (99% of the times this is the cause of the fault)
  • suggest searching the PC in the nordic forums

For NRF_FAULT_ID_APP_MEMACC:

  • explain the cause, print the PC value.

It'd be great to get probe-run and other tools to print a stack trace on NRF_FAULT_ID_APP_MEMACC but I'm not sure if it's possible :S

Cannot build the example having built the library

Having difficulty getting started with an example noting that I've successfully run the test-build.sh script.

As per the README, if I try:

cargo run --bin ble_bas_peripheral

...then:

% cargo run --bin ble_bas_peripheral 
   Compiling nrf-softdevice-s140 v0.1.1 (/Users/huntc/Projects/hacking/nrf-softdevice/nrf-softdevice-s140)
   Compiling cortex-m-rt v0.6.13
warning: unused import: `core::str::FromStr`
 --> nrf-softdevice-macro/src/lib.rs:5:5
  |
5 | use core::str::FromStr;
  |     ^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: 1 warning emitted

   Compiling nrf52840-pac v0.9.0
   Compiling panic-probe v0.1.0
LLVM ERROR: Global variable 'Reset' has an invalid section specifier '.Reset': mach-o section specifier requires a segment and section separated by a comma.
error: could not compile `cortex-m-rt`

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: invalid register `r0`: unknown register
    --> nrf-softdevice-s140/src/bindings.rs:1737:9
     |
1737 |         inout("r0") to_asm(p_mutex) => ret,
     |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: invalid register `r1`: unknown register
    --> nrf-softdevice-s140/src/bindings.rs:1738:9
     |
1738 |         lateout("r1") _,
     |         ^^^^^^^^^^^^^^^

error: invalid register `r2`: unknown register
    --> nrf-softdevice-s140/src/bindings.rs:1739:9

...and many more. I've also tried enabling features:

cargo run --features s140,nrf52840,ble-central,ble-peripheral,ble-l2cap,ble-gatt-client,ble-gatt-server --bin ble_bas_peripheral

Use of `cortex_m::interrupt::free` in examples

In the readme you say that you should never use cortex_m::interrupt::free because of softdevice. However, in the examples the alloc-cortex-m crate is used, which uses cortex_m::interrupt::free in their implementation here.

nrf51 series

Is there an alternative package for the nrf51 series, or how difficult would it be to support?

API to build advertising data

Right now, to build data packets, we have to do something like:

    #[rustfmt::skip]
    let adv_data = &[
        0x02, 0x01, raw::BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE as u8,
        0x03, 0x03, 0x09, 0x18,
        0x0a, 0x09, b'H', b'e', b'l', b'l', b'o', b'R', b'T', b'I', b'C',
    ];
    #[rustfmt::skip]
    let scan_data = &[
        0x03, 0x03, 0x09, 0x18,
    ];

We need an API to build those array without having to fiddle with bytes.

I'd like to help, but I could not find the reference documentation for those data packet.

I guessed that adv_data is an array of length(1byte), type(1byte), data(length - 1 bytes). But I am not very familiar with BLE and found dozen of different documentation with no real reference for this.

Error reported via Rust Analyzer in VS Code

I'm seeing VS Code's Rust Analyzer complain about an error with ScanConfig, yet I'm bewildered as to why. I'm able to jump into ScanConfig and can see the declaration of tx_power that it requires. Here's a screenshot:

image

Macro error

I'm trying to dive in and try your set of crate, but I have an error that maybe you have an idea where it originates from:

error[E0425]: cannot find value `irq` in this scope
   --> /home/kuon/.cargo/git/checkouts/nrf-softdevice-9b99539d60cc72a7/52329d2/nrf-softdevice/src/util/macros.rs:30:40
    |
30  |                 defmt::error!($msg, $( $i ),*);
    |                                        ^^ not found in this scope
    |
   ::: /home/kuon/.cargo/git/checkouts/nrf-softdevice-9b99539d60cc72a7/52329d2/nrf-softdevice/src/interrupt.rs:248:5
    |
248 |     assert_app_accessible_irq!(irq);
    |     -------------------------------- in this macro invocation
    |

nrf-softdevice-gen broken

Fallout from #1

moving the .cargo/config up means nrf-softdevice-gen is currently broken unless you pass an override --target or just comment out the target in .cargo/config

Mixing std and no_std in a single workspace is kind of a pain

You probably want to move it outside the other no_std stuff or the entire repo?

Receive notifications in gatt_client

Is there a way for gatt_client to receive notifications? I am trying to understand nrf-softdevice-macro and I see there is some sort of event generated in nrf-softdevice-macro/src/lib.rs:

if notify {
    let case_notification = format_ident!("{}Notification", name_pascal);
    code_event_enum.extend(quote_spanned!(ch.span=>
        #case_notification(#ty),
    ));
}

But how do I capture it, there is no gatt_client::run() like there is with gatt_server? Maybe I'm looking in the wrong places..

Happy to contribute documentation and/or code if I can just get a little hint!

entered unreachable code at Portal<T>::wait_once

I'm seeing this error in production somewhat rarely. I haven't been able to repro it yet.

 ERROR device            > 93281.127 panicked at 'internal error: entered unreachable code'
stack backtrace:
   0: core::panicking::panic
        at /root/.rustup/toolchains/nightly-2021-10-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panicking.rs:41
   1: __defmt_default_panic
        at /root/.cargo/git/checkouts/defmt-7f5b74b4e6ff55d4/50e3db3/defmt/src/lib.rs:367
   2: nrf_softdevice::util::portal::Portal<T>::wait_once::{{closure}}::{{closure}}
   3: nrf_softdevice::util::portal::Portal<T>::call
   4: nrf_softdevice::ble::on_evt
   5: nrf_softdevice::events::run::{{closure}}::{{closure}}
        at /root/.cargo/git/checkouts/nrf-softdevice-c6f1e1abd1ad6893/6a01c4c/nrf-softdevice/src/events.rs:73
   6: <futures_util::future::poll_fn::PollFn<F> as core::future::future::Future>::poll
        at /root/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.18/src/future/poll_fn.rs:56
   7: nrf_softdevice::events::run::{{closure}}
        at /root/.cargo/git/checkouts/nrf-softdevice-c6f1e1abd1ad6893/6a01c4c/nrf-softdevice/src/events.rs:54
   8: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
        at /root/.rustup/toolchains/nightly-2021-10-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:80
   9: nrf_softdevice::softdevice::Softdevice::run::{{closure}}
        at /root/.cargo/git/checkouts/nrf-softdevice-c6f1e1abd1ad6893/6a01c4c/nrf-softdevice/src/softdevice.rs:323
  10: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
        at /root/.rustup/toolchains/nightly-2021-10-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:80
  11: application::ble::softdevice_task::task::{{closure}}
        at /builds/firmware/firmware/ak-application/src/application/ble.rs:131
  12: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
        at /root/.rustup/toolchains/nightly-2021-10-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:80
  13: embassy::executor::raw::TaskStorage<F>::poll
        at /root/.cargo/git/checkouts/embassy-00cf184034ab5a1f/7561fa1/embassy/src/executor/raw/mod.rs:183
  14: core::cell::Cell<T>::get
        at /root/.rustup/toolchains/nightly-2021-10-16-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cell.rs:436
  15: embassy::executor::raw::timer_queue::TimerQueue::update
        at /root/.cargo/git/checkouts/embassy-00cf184034ab5a1f/7561fa1/embassy/src/executor/raw/timer_queue.rs:35
  16: embassy::executor::raw::Executor::poll::{{closure}}
        at /root/.cargo/git/checkouts/embassy-00cf184034ab5a1f/7561fa1/embassy/src/executor/raw/mod.rs:329
  17: embassy::executor::raw::run_queue::RunQueue::dequeue_all
        at /root/.cargo/git/checkouts/embassy-00cf184034ab5a1f/7561fa1/embassy/src/executor/raw/run_queue.rs:71
  18: embassy::executor::raw::Executor::poll
        at /root/.cargo/git/checkouts/embassy-00cf184034ab5a1f/7561fa1/embassy/src/executor/raw/mod.rs:308
  19: cortex_m::asm::inline::__wfe
        at /root/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-0.7.3/src/../asm/inline.rs:177
  20: cortex_m::asm::wfe
        at /root/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-0.7.3/src/asm.rs:49
  21: embassy::executor::arch::Executor::run
        at /root/.cargo/git/checkouts/embassy-00cf184034ab5a1f/7561fa1/embassy/src/executor/arch/cortex_m.rs:54
  22: application::sys::__cortex_m_rt_main
  23: application::sys::__cortex_m_rt_main
        at /builds/firmware/firmware/ak-application/src/application/../sys.rs:158
error: the stack appears to be corrupted beyond this point

Make Softdevice::enable fully safe by taking ownership of the forbidden peripherals

Currently the user can enable the softdevice and then use the forbidden peripherals, which will cause undefined behavior or softdevice faults.

The way of fixing this is forcing enable() to take owned instances of the forbidden PAC peripherals.

The forbidden peripherals for s140 are:

RADIO
RTC0
TIMER0
RNG
ECB
CCM_AAR
TEMP
SWI5_EGU5

How to have exclusive connection

How can I do the following?

  • start advertizing
  • when I got a connection, stop advertizing and don't accept new connection
  • restart advertizing when the connection is closed by the the client

Now in my advertize loop, I have the following:

    loop {
        info!("Advertising start!");
        let conn = peripheral::advertise(
            sd,
            peripheral::ConnectableAdvertisement::ScannableUndirected {
                adv_data,
                scan_data,
            },
        )
        .await
        .dewrap();

        info!("Advertising done!");

        // Detach the connection so it isn't disconnected when dropped.
        conn.detach();
    }

I feel like I should do some loop instead of conn.detach() but I don't know if you exposed the APIs yet.

Data Length Extension negotiation

The BLE data length extension must be negotiated using sd_ble_gap_data_length_update and events on_data_length_update_request, on_data_length_update

Nordic's equivalent code is in nrf_ble_gatt.c

Setting gatt value from interrupts

I see that many things changed in the codebase.

I am also back on my ble project, and I am trying to have a gatt server working.

I am looking at: https://github.com/akiles/nrf-softdevice/blob/master/examples/src/bin/ble_bas_peripheral.rs

How am I supposed to set the gatt server value from within the code? I mean, for example, imagine I have a timer interrupt in which I read some values from an i2c peripheral, how can I write it to BatteryService.foo for currently connected devices to get the update? (I still use rtic, but I don't think it should change much)

More efficient handling of 128-bit uuids

The softdevice handles 128bit uuids in a funny manner: you register them at runtime to get an "uuid type", and then to use it you specify the type, and bytes 12-13. This means if you do a custom service that requires many UUIDs, you can save flash and ram by making them only differ in bytes 12-13: you only register the "base" uuid once, then use the same uuid type with just different bytes 12-13.

If we want to take advantage of this we could make a macro like this:

uuids!(
    FOO_SVC = "4a04fbec-229b-11eb-98bd-2f03a9d5f786";
    FOO_CHAR_1 = "4a04fbec-229b-11eb-98bd-2f030000f786";
    FOO_CHAR_2 = "4a04fbec-229b-11eb-98bd-2f030001f786";
    FOO_CHAR_3 = "4a04fbec-229b-11eb-98bd-2f030002f786";
    FOO_CHAR_4 = "4a04fbec-229b-11eb-98bd-2f030003f786";
    FOO_CHAR_5 = "4a04fbec-229b-11eb-98bd-2f030004f786";
    FOO_CHAR_6 = "4a04fbec-229b-11eb-98bd-2f030005f786";
)

which would generate code to register the "base uuid" just once if uuids are equal in bytes other than 12-13

Upgrade to sdk 17.0.2

No hurry, I more wanted to document that the current softdevice thats checked in (do you want to check that in?) and the generated files are from 16.0.0

Bond Management Service missing?

I was trying to restrict who can connect over Bluetooth to a device. To my understanding (and I don't really have much understanding of Bluetooth) I would need to bind the connection. And that is what the "Bond Management Service" is for.

However, I couldn't find anything related to that in nrf-softdevice. Is that just missing, or is there another way to deal with this?

Update examples to work with latest embassy

Latest embassy always requires a clock to be set (this itself may be an embassy bug, have to look into it).

Either way, the examples should Just Work and they don't right now. They're missing manual clock setup like the following, or a way to set the irq priority with #[embassy::main]

    unsafe { embassy_nrf::system::configure(Default::default()) };

    let irq = interrupt::take!(RTC1);
    irq.set_priority(Priority::Level3); // levels 0-1 are reserved for the softdevice
    let rtc = unsafe { embassy_nrf::peripherals::RTC1::steal() };
    let rtc = RTC.put(rtc::RTC::new(rtc, irq));
    rtc.start();
    unsafe { embassy::time::set_clock(rtc) };

Support `run`ing multiple GATT services

Right now, you can register multiple GATT services and call their set/get/notify methods in parallel. However, you can't have multiple registered services subscribed to events since gatt_server::run uses a portal internally.
A workaround right now is to create dummy wrapper server that dispatches to each individual service, but that's pretty hack-y.

It would be nice to have a run macro that could support multiple services, e.g.:

let srv_a: ServiceA = unwrap!(gatt_server::register(sd));
let srv_b: ServiceB = unwrap!(gatt_server::register(sd));
...
let res = gatt_server::run!(&conn,
  &srv_a, |_e| defmt::info!("Handle service A event"),
  &srv_b, |_e| defmt::info!("Handle service B event"),
).await;

As far as I can tell, this interface would be feasible to implement as the macro would just need to internally chain the servers' on_write methods.

Using with cortex-m-rtic

I tried to use the softdevice with cortex-m-rtic, but if I specify "peripherals=true" and try to access CLOCK, I got the following crash

1879│                 None
1880│             } else {
1881│                 Some(unsafe { Peripherals::steal() })
1882│             }
1883│         })
1884│     }
1885│     #[doc = r"Unchecked version of `Peripherals::take`"]
1886│     #[inline]
1887│     pub unsafe fn steal() -> Self {
1888├───────> DEVICE_PERIPHERALS = true;
1889│         Peripherals {
1890│             FICR: FICR {
1891│                 _marker: PhantomData,
1892│             },
1893│             UICR: UICR {
1894│                 _marker: PhantomData,
1895│             },
1896│             CLOCK: CLOCK {
1897│                 _marker: PhantomData,
/home/kuon/.cargo/registry/src/github.com-1ecc6299db9ec823/nrf52840-pac-0.9.0/src/lib.rs
35                  hal::clocks::Clocks::new(cx.device.CLOCK).enable_ext_hfosc();
Breakpoint 1 at 0x2724c
Breakpoint 2 at 0x27264
Function "rust_begin_unwind" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
Breakpoint 3 at 0x271e4: file src/main.rs, line 22.
semihosting is enabled

Loading section .vector_table, size 0x100 lma 0x27000
Loading section .text, size 0x12c lma 0x27100
Start address 0x00027100, load size 556
Transfer rate: 1 KB/sec, 278 bytes/write.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 3, nrf52840_pac::Peripherals::steal () at /home/kuon/.cargo/registry/src/github.com-1ecc6299db9ec823/nrf52840-pac-0.9.0/src/lib.rs
:1888
1888            DEVICE_PERIPHERALS = true;
(gdb)

And if I try to use it with no peripherals, I got the following crash:

 4│
 5│ pub use bare_metal::{CriticalSection, Mutex, Nr};
 6│
 7│ /// Disables all interrupts
 8│ #[inline]
 9│ pub fn disable() {
10│     match () {
11│         #[cfg(all(cortex_m, feature = "inline-asm"))]
12│         () => unsafe {
13├───────────> llvm_asm!("cpsid i" ::: "memory" : "volatile");
14│         },
15│
16│         #[cfg(all(cortex_m, not(feature = "inline-asm")))]
17│         () => unsafe {
18│             extern "C" {
19│                 fn __cpsid();
20│             }
21│
22│             // XXX do we need a explicit compiler barrier here?
/home/kuon/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-0.6.3/src/interrupt.rs
13                  llvm_asm!("cpsid i" ::: "memory" : "volatile");
Breakpoint 1 at 0x271d0
Breakpoint 2 at 0x271e8
Function "rust_begin_unwind" not defined.
Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]
Breakpoint 3 at 0x271b4: file src/main.rs, line 22.
semihosting is enabled

Loading section .vector_table, size 0x100 lma 0x27000
Loading section .text, size 0xec lma 0x27100
Start address 0x00027100, load size 492
Transfer rate: 1 KB/sec, 246 bytes/write.
Note: automatically using hardware breakpoints for read-only addresses.

Breakpoint 3, cortex_m::interrupt::disable () at /home/kuon/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-0.6.3/src/interrupt.rs:1
3
13                  llvm_asm!("cpsid i" ::: "memory" : "volatile");
(gdb)

Should I not try to use rtic and consider it incompatible with the softdevice?

Freeze after Disconnect

When I run any of the ble_bas_peripheral example, the device (nrf52840 dk) seems to freeze. It does not go back to advertising nor are there any tracing messages. I also ran the gatt server from within the rtic example and the tick task seems to stop as well.
The disconnect event is not logged before that happens.

It feels like this is actually the softdevice crashing, but maybe it is not configured correctly. Any idea what could cause this or how to track it down?

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.