nrf-rs / nrf-hal Goto Github PK
View Code? Open in Web Editor NEWA Rust HAL for the nRF family of devices
License: Apache License 2.0
A Rust HAL for the nRF family of devices
License: Apache License 2.0
Currently there's nrf52 and nrf9160 crates in this repo, I think it'd be better if that was split up, or if the repo name reflected the contents of the repo. Maybe a generic "nrf-hal"?
It would be nice to have a safe, ergonomic API to setup events and tasks using the GPIOTE module.
I have an example of how the PAC can be used directly, tested out on the nrf52 dev kit.
I'm up for giving this a go.
I'm guessing it's going to be kind of similar to the gpio
module but with more layers. Also I'm wondering about the best way to handle the multiple channels.
It definitely needs a typestate to indicate whether an event pin is configured as pullup or pulldown as a floating pin had me scratching my head for a while.
Does anyone have any hints or implementations they know of in other HAL crates that deal with similar functionality?
Hello!
If I started work on an nrf52810-hal
is it the sort of thing you would like to see merged, or developed as a separate project? I can't see any references to it in this repository so I was just wondering what the plans were.
Thanks :)
This name could conflict with core::pin::Pin
. We might want to rename it IOPin
, or GpioPin
, or similar.
We should decide this before the 0.8.0 release.
The nrf51-hal
recently added an interface to the temperature sensor: nrf-rs/nrf51-hal#17
A similar/identical implementation for nrf52-hal
would be nice.
This repository should focus on HALs for the microcontrollers, not on providing support for every conceivable devboard that contributors might not have. Board specific crates should be moved to their own repository.
This issue was first opened in the old nrf52-hal repository. Original discussion: jamesmunns/nrf52-hal#8
Most of the code in the GPIO module is generated using a macro, including all the types that represent pins. Through my experience working on lpc82x-hal, I've come to regard this as an anti-pattern.
To be clear, I'm not suggesting that we don't generate code using a macro. I'm suggesting that we minimize the amount of generated code, using it only to feed platform-specific bits into generic, hand-written code.
But more on my suggestion later. First, the reasons on why I regard generating everything (specifically all pin types) as an anti-pattern:
Argument 1. is fairly self-evident, but argument 2. might seem a bit a bit esoteric. It does have real consequences, however. Consider a wrapper type around a pin that is generic over the pin, but specific about the state. Currently, this would require higher-kinded types to express:
struct PinWrapper<T>(T<Output<PushPull>>);
Since higher-kinded types don't exist in Rust, you'd have to use the generic pin type, making the wrapper type less type-safe than it could be:
struct PinWrapper(P0_Pin<Output<PushPull>>);
See dwm1001 for a real-life example of this problem.
I've encountered this same problem with lpc82x-hal and came up with the following solution:
This would look something like this. First, the generic Pin
type:
struct Pin<T, Mode> { ... }
Pin
relies on traits to do whatever it needs to do:
impl<T> Pin<T, Output> where T: PinTrait {
pub fn do_stuff(&mut self) {
T::do_stuff();
}
}
A code generation macro would still exist, but it would only generate the bare minimum: Types like P0_12
and their trait implementations. lpc82x-hal has several implementations of this pattern: Pin, Function
Now type of pin and mode of pin are cleanly separated, and all combinations can be cleanly expressed:
struct FullyGeneric<T, Mode>(Pin<T, Mode>);
struct TypeGeneric<T>(Pin<T, Output>);
struct ModeGeneric<Mode>(Pin<P0_12, Mode>);
struct FullySpecific(Pin<P0_12, Output);
P0_Pin
and degrade
would no longer be necessary.
There's one drawback that I never found a good solution for: Whereever you implement this pattern, you end up with a struct, e.g. Thing
and a trait that really wants to have the same name. I've been calling these traits ThingTrait
instead. This is not pretty, but okay. I'm open to any suggestions!
I'm currently trying to get the SAADC working for a project, and thought that adding it to the HAL would be a nice addition. I think I'd start with just a blocking implementation, does anyone have any rough ideas as to how the API should be structured?
See stm32-rs/stm32f4xx-hal#6, I made a mistake in the original stm32f103xx code that our impl is based on
The crates in this repository currently don't have a changelog, and therefore no convenient way to check out what changed in new releases.
It's currently not clear to me what the best way to do this would be. Just copy-past the changes from nrf52-hal-common
to all nrf528xx-hal
changelogs?
SPIM::transfer_split_uneven seems to send only logic low when the rx_buffer is a Zero Sized Slice. Could it be because the Rust compiler is optimizing out operations on the zero sized type? I'm still new to this but replicating the first part of the transfer_split_uneven function on my desktop compiled to no output.
Full code below (running on a nRF52-DK). If i substitute read() with a zero sized array, for the write() I get the same result:
#![no_std]
#![no_main]
extern crate panic_halt;
extern crate nrf52832_hal;
extern crate embedded_hal_spy;
use cortex_m_rt::entry;
use nrf52832_hal::gpio::{self, *, p0::*, Level};
use nrf52832_hal::spim::Spim;
#[entry]
fn main() -> ! {
let p = nrf52832_hal::pac::Peripherals::take().unwrap();
let port0 = p0::Parts::new(p.P0);
let cs: P0_12<gpio::Output<PushPull>> = port0.p0_12.into_push_pull_output(Level::High);
let spiclk = port0.p0_24.into_push_pull_output(Level::Low).degrade();
let spimosi = port0.p0_23.into_push_pull_output(Level::Low).degrade();
let spimiso = port0.p0_22.into_floating_input().degrade();
let pins = nrf52832_hal::spim::Pins {
sck: spiclk,
miso: Some(spimiso),
mosi: Some(spimosi),
};
let mut spi = Spim::new(
p.SPIM1,
pins,
nrf52832_hal::spim::Frequency::K500,
nrf52832_hal::spim::MODE_0,
0,
);
let data: [u8; 1] = [0b1101_0010];
//let mut readbuf: [u8; 0];
//spi.write(&mut cs.degrade(), &data).unwrap();
spi.read(&mut cs.degrade(), &data, &mut [0u8; 0]).unwrap();
loop {}
}
There are two peripheral access crates that the crates in this repository depend on, but that are not currently living under this organization nrf52 and nrf52840. Would the authors consider transitioning those crates to the nrf-rs organization?
If we do transition those repositories, nrf52 should be renamed to nrf52832.
cc @jamesmunns, @wez, @jscarrott
Hi, I'm pretty new to Rust so apologies if this is something obvious on my end. When cloning the repo and running cargo build
, I get the error shown below. I am using Ubuntu 19.10 and rustc version 1.44.0.
jason@faraday:/media/jason/e/projects/nrf-hal$ cargo build
Compiling cortex-m v0.6.2
Compiling typenum v1.12.0
Compiling semver-parser v0.7.0
Compiling stable_deref_trait v1.1.1
Compiling vcell v0.1.2
Compiling proc-macro2 v1.0.18
Compiling unicode-xid v0.2.0
Compiling syn v1.0.31
Compiling cortex-m-rt v0.6.12
Compiling r0 v0.2.2
Compiling void v1.0.2
Compiling nb v0.1.2
Compiling nrf52832-pac v0.9.0
Compiling nrf52833-pac v0.9.0
Compiling nrf9160-pac v0.2.1
Compiling nrf51 v0.9.0
Compiling nrf52840-pac v0.9.0
Compiling fpa v0.1.0
Compiling nrf52810-pac v0.9.0
Compiling rand_core v0.5.1
Compiling memchr v2.3.3
Compiling proc-macro2 v0.4.30
Compiling nrf52832-hal v0.10.0 (/media/jason/e/projects/nrf-hal/nrf52832-hal)
Compiling unicode-xid v0.1.0
Compiling version_check v0.9.2
Compiling version_check v0.1.5
Compiling rand_core v0.4.2
Compiling syn v0.15.44
Compiling byteorder v1.3.4
Compiling cortex-m-semihosting v0.3.5
Compiling nrf9160-hal v0.10.0 (/media/jason/e/projects/nrf-hal/nrf9160-hal)
Compiling heapless v0.4.4
Compiling cortex-m v0.5.10
Compiling panic-halt v0.2.0
Compiling aligned v0.2.0
Compiling ufmt-write v0.1.0
Compiling ssd1306 v0.2.6
Compiling cortex-m-rtfm v0.4.3
Compiling nrf52840-hal v0.10.0 (/media/jason/e/projects/nrf-hal/nrf52840-hal)
Compiling nrf51-hal v0.10.0 (/media/jason/e/projects/nrf-hal/nrf51-hal)
Compiling adafruit-nrf52-bluefruit-le v0.0.1 (/media/jason/e/projects/nrf-hal/boards/adafruit-nrf52-bluefruit-le)
Compiling nrf52833-hal v0.10.0 (/media/jason/e/projects/nrf-hal/nrf52833-hal)
Compiling nrf52810-hal v0.10.0 (/media/jason/e/projects/nrf-hal/nrf52810-hal)
Compiling volatile-register v0.2.0
Compiling semver v0.9.0
Compiling embedded-hal v0.2.3
Compiling rand_core v0.3.1
Compiling nom v5.1.2
Compiling nom v4.2.3
Compiling embedded-hal-spy v0.0.3
Compiling rand v0.5.6
Compiling rustc_version v0.2.3
Compiling hash32 v0.1.1
Compiling quote v1.0.7
Compiling quote v0.6.13
Compiling bare-metal v0.2.5
Compiling cast v0.2.3
Compiling tinytga v0.1.0
Compiling generic-array v0.13.2
Compiling generic-array v0.12.3
Compiling generic-array v0.11.1
Compiling as-slice v0.1.3
Compiling aligned v0.3.2
Compiling rtt-target v0.2.0
Compiling panic-semihosting v0.5.3
Compiling tinybmp v0.1.1
Compiling embedded-graphics v0.4.9
Compiling owned-singleton-macros v0.1.0
Compiling cortex-m-rtfm-macros v0.4.3
Compiling cortex-m-rt-macros v0.1.8
Compiling owned-singleton v0.1.0
Compiling ecb-demo v0.0.1 (/media/jason/e/projects/nrf-hal/examples/ecb-demo)
error[E0432]: unresolved import `hal`
--> examples/ecb-demo/src/main.rs:22:5
|
22 | hal::{Clocks, Ecb},
| ^^^ use of undeclared type or module `hal`
error[E0433]: failed to resolve: use of undeclared type or module `hal`
--> examples/ecb-demo/src/main.rs:34:13
|
34 | let p = hal::pac::Peripherals::take().unwrap();
| ^^^ use of undeclared type or module `hal`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0432, E0433.
For more information about an error, try `rustc --explain E0432`.
error: could not compile `ecb-demo`.
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed
This issue was first opened in the old nrf52-hal repository. Original discussion: jamesmunns/nrf52-hal#6
The entry points to this crate's API are currently mostly extension traits: For a peripheral that this crate provides an API for, an extension trait is defined and implemented. Extension traits are implemented for the peripheral proxys from the nrf52
crate. An extension trait defines a method like constrain
or split
, which consumes the raw peripheral proxy and returns the HAL API for that peripheral.
That style of API is popular among HAL APIs (I think mostly because most HAL crates start out by copying other HAL crates), but I believe it is flawed. The critical problem is, that the HAL can't control the initial hardware state, making it impossible to give certain guarantees without significant runtime overhead. If we knew for a fact that no one had been messing with the hardware before initializing the HAL API, we could give much stronger safety guarantees, without the additional runtime overhead.
So far this is a rather general argument, but there is one concrete problem that would be weird to solve with the extension trait style: On the nRF52, several groups of peripherals share the same address space, and only one peripheral in each group can be used at a time (see nRF52832 Product Specification, section 15.2).
If we controlled the initial hardware state, we could statically guarantee that the user can enable only one of the peripherals in a given address space at a time. With the the current architecture, I can only think of solutions that are weird (enabling one peripheral in the group consumes the others) or less efficient (check hardware status at runtime.
I propose the following architecture:
Peripherals
, which wraps nrf52::Peripherals
and nrf52::CorePeripherals
.Peripherals
has two methods that can be used to get an instance, take
and steal
.take
and steal
use the take
and steal
methods of nrf52::Peripherals
/nrf52::CorePeripherals
to provide the same guarantees that those methods provide.Peripherals
. For peripherals that don't have a HAL API implemented yet, the peripheral proxy from nrf52
is provided directly.free
method that returns the peripheral proxy from nrf52
. This allows the user to fall back to the raw register API, if the HAL API doesn't fulfill their needs.Peripherals
. Those are consumed by the HAL APIs of the shared peripherals when enabling them.Summary: By following this architecture, we know that the user hasn't modified the hardware at the point when the HAL API is initialized (unless they have used unsafe
means to do so, at which point all bets are off). This allows us to provide safety guarantees that we otherwise couldn't provide easily, or only with additional runtime overhead.
Further reading: I've been using this technique in lpc82x-hal
for a while now, and I'm very happy with it. One major problem it solves is pin function assignment. lpc82x-hal
statically guarantees that conflicting pin functions can't be assigned to a single pin. Without control over the initial hardware conditions, this could not be achieved without checking every single function assignment register (nRF52 has the same problem, by the way).
As per @jamesmunns wishes in https://github.com/nrf-rs/nrf52-hal/diffs/4_ this issue should track the open questions about the missing BPROT register on the nRF52840. For now it's just not accessible through the nRF52840-DK BSP as it's apparently also missing in the pac.
We need to find out:
edit: and ofc the given link by GH does not work. Dunno how to reference the location before the merge. Will relink once it's merged.
I would like to request that we require all members of the organization to use 2FA. Because the teams of this organization have access to push to crates.io, if an attacker can compromise one of our accounts, they can push malicious code to crates.io.
In general, EasyDMA does not work with items in Flash, e.g. a &'static str
. From the datasheet:
EasyDMA is an easy-to-use direct memory acc s module that some peripherals implement to gain direct access to Data RAM.
The EasyDMA is an AHB bus master similar to the CPU and it is connected to the AHB multilayer
interconnect for direct access to the Data RAM. The EasyDMA is not able to access the Flash.
I did this accidentally, and did not receive any visible error when sending via UARTE. I think there would be 3 ways to address this:
debug_assert
that the slice ptr is in the RAM regionif !( RAM_LOWER <= buf.as_ptr() <= RAM_UPPER ) { return Err(...); }
I try to compile mi first blink for nrf52840 uC and review your examples for learning and see use directly set_low()
after creating Pin instance with into_push_pull_output
follow this example: https://github.com/nrf-rs/nrf-hal/blob/master/examples/spi-demo/src/main.rs#L31
this is my code
#![no_std]
#![no_main]
extern crate panic_halt;
use cortex_m_rt::entry;
extern crate nrf52840_hal;
use nrf52840_hal::gpio;
use nrf52840_hal::gpio::*;
use nrf52840_hal::gpio::p0::*;
use nrf52840_hal::Timer;
#[entry]
fn main() -> ! {
let p = nrf52840_hal::pac::Peripherals::take().unwrap();
let p0 = p0::Parts::new(p.P0);
let mut led1: P0_24<gpio::Output<PushPull>> = p0.p0_24.into_push_pull_output(Level::High);
let mut timer = Timer::new(p.TIMER0);
loop {
led1.set_low();
timer.delay(2_000_000);
led1.set_high();
timer.delay(2_000_000);
}
}
And this is an error message, both equal for set_low
and set_high
error[E0599]: no method named `set_low` found for struct `nrf52840_hal::gpio::p0::P0_24<nrf52840_hal::gpio::Output<nrf52840_hal::gpio::PushPull>>` in the current scope
--> src/main.rs:26:14
|
26 | led1.set_low();
| ^^^^^^^ method not found in `nrf52840_hal::gpio::p0::P0_24<nrf52840_hal::gpio::Output<nrf52840_hal::gpio::PushPull>>`
Use this debs
[dependencies]
nrf52840-hal = "0.11.0"
cortex-m-rt = "0.6.12"
panic-halt = "0.2.0"
Right now, it is not possible to obtain back the pins used to create a Uarte.
Documentation is sorely lacking right now. It would be great to have a more useful README.
nrf52-hal
is actually specific to nRF52832, so the current name is highly misleading in this context.
Right now, RXD and CTS of Uarte::Pins are of type output. This is wrong.
https://github.com/nrf-rs/nrf52-hal/blob/master/nrf52-hal-common/src/uarte.rs#L172-L177
From the datasheet:
UARTE signal | UARTE pin | Direction | Output value |
---|---|---|---|
RXD | As specified in PSEL.RXD | Input | N/A |
CTS | As specified in PSEL.CTS | Input | N/A |
RTS | As specified in PSEL.RTS | Output | 1 |
TXD | As specified in PSEL.TXD | Output | 1 |
For compat reasons, we should support implicit copy (if the user passes in a slice from .text
) of chunks on all interfaces. We currently do this for UARTE, but not for SPIM/TWIM.
This repository contains HAL crates for nRF52 microcontrollers. I think the repository name should reflect that, especially since throughout the ecosystem, repositories that are named after a chip (without the -hal
suffix) seem to contain peripheral access crates, not HAL crates.
cc @wez
The current SPIM implementation hardcodes the frequency, mode and over-read character, is this for hardware reasons, or could I work on a PR that makes it configurable (same API as in https://docs.rs/stm32f1xx-hal/0.2.0/stm32f1xx_hal/spi/struct.Spi.html)?
For example:
let p0 = p0::Parts(p.P0);
let a = p0.p0_00.degrade();
let mut b = p0.p0_01.degrade();
b.pin = 0;
Lets you create 2 P0.00 pins. I don't think this operation is UB per se but it does break the intended (singleton) semantics and can result in IO misconfiguration, e.g. configuring P0.00 both as serial Tx and Rx if you pass the a
and b
from above to the Uarte
abstraction.
Setting the public pin
field to value equal or greater than 32
may result in out of bounds array access though (either a panic or UB if the HAL is using unchecked bounds access).
I think making the fields private and instead providing getter methods for pin
and port
would be a better fit here.
I notice that with adafruit-nrf52-bluefruit-le board crate, its built of of much newer abstractions around GPIO pins that are only in the unreleased nrf52-hal-common in git. I'm wondering when the next release of nrf52-hal-common will be so that I can build off newer abstractions without having to use a path dependency.
I'm curious if there's a thought process on when things get released?
When merging pull requests, the option "Create a merge commit" is currently disabled in this repository. I actually prefer that option, as it documents in the commit history which commits belong to larger pieces of work.
"Squash and merge" is currently enabled. I suggest disabling it, as that makes it easy to accidentally lose valuable history, especially since it's currently the default option. Whenever squashing commits is desirable, it's easy enough to do manually.
I'd also prefer to disable "Rebase and merge", due to my preference for merge commits. I don't feel strongly about this point.
cc @nrf-rs/team, especially @wez
I am poking around a nRF52840-DK.
I'm trying to implement a blinky for starters, but run into a puzzling compilation error.
error[E0599]: no function or associated item named `new` found for struct `nrf52_hal_common::gpio::p0::Parts` in the current scope
--> examples/blinky.rs:19:28
|
19 | let port0 = p0::Parts::new(peripherals.P0);
| ^^^ function or associated item not found in `nrf52_hal_common::gpio::p0::Parts`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.
error: could not compile `nrf52840-dk`.
To learn more, run the command again with --verbose.
Source code:
#![no_main]
#![no_std]
use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
#[allow(unused_imports)]
use panic_semihosting;
use nrf52840_hal as hal;
use hal::nrf52840_pac as pac;
use hal::gpio::p0;
#[entry]
fn main() -> ! {
hprintln!("Hello, world!").unwrap();
let peripherals = pac::Peripherals::take().unwrap();
let port0 = p0::Parts::new(peripherals.P0);
loop {}
}
Cargo.toml (packaged info omitted):
[dependencies]
cortex-m = { version = "0.5.4", features = [ "const-fn" ] }
cortex-m-rt = "0.6.12"
embedded-hal = "0.2.3"
nrf52840-hal = "0.8.1"
[dev-dependencies]
cortex-m-rt = "0.6.12"
cortex-m-semihosting = "~0.3"
panic-semihosting = "~0.5"
nb = "~0.1"
[features]
rt = ["nrf52840-hal/rt"]
default = ["rt"]
I based this on the SPI example.
I took a very quick look a the gpio.rs file and if I correctly read the macro at the bottom, there should be a public method new
implemented for p0::Parts
On the other hand, when looking at the HAL's documentation on doc.rs there is no new
method implemented for p0::Parts
.
From my naive point of view one of the following is happening:
Can anyone help me figure that one out ?
CC @hannobraun, could you please add the nrf-rs/nrf52 team as an owner for the nrf52810 crate? Right now you are the only owner.
Edit: On crates.io. You can do this by running the following command from within the crate locally:
cargo owner --add github:nrf-rs:nrf52
The SAADC can have multiple channels, and starting the sample
task will result in all channels being read and DMA'd into memory. This is a useful feature and should probably be exposed somehow, but the specifics need to be discussed.
It would most likely interfere with the embedded-hal OneShot
trait, so perhaps a MultiShot
trait could be proposed?
The SAADC is also dual-rail, so discussion needs to be had regarding how that should be exposed.
We should consider creating an nrf52 team on GitHub under this organization, and give this team access to all related repositories and crates. This would keep access management concentrated in one place (GitHub), allow everyone to release new crate versions as necessary, and make it easier to tag the relevant people on any issues.
I'm working on embedded-platform
and am targeting nrf52840
devices as the first use-case.
Currently, I'm using this code to support serial writes: https://github.com/dflemstr/embedded-platform/blob/f9ae5e7b686fdbf66ee3f172c755aea543d4c102/platforms/nrf52840/src/serial.rs#L19-L23
I haven't started on SPI/I²C/... mappings but I suspect there will be similar challenges in making the code non-blocking.
The execution model I have chosen is to have the main thread always run wfi
when there is nothing happening, and rely on interrupts to wake it up, poll a main future, and do some work, before going back to wfi
.
Ideally, the baseline behavior I would like to see is to break apart some of the blocking transactions into multiple steps. Let's look at this section for example:
This could either be modeled as an explicit state machine (e.g. an enum
) where during each state transition, there is some sort of polling method instead of a while loop. So imagine a SerialTransaction
object with a poll()
method that would eventually return a successful status.
If this approach sounds sane, I can make it into a PR.
For sending multiple blocks of data for things like Spim::transfer, this is a handy pattern I came up with. Not sure if it compiles to more code:
fn send(&mut self, buf: &[u8]) -> Result<(), ()> {
for c in buf.chunks(EASY_DMA_SIZE) {
self.scratch[..c.len()]
.copy_from_slice(c);
self.uart.write(&self.scratch[..c.len()]).map_err(|_| ())?;
}
Ok(())
}
I think it would be useful to add resources such as reference manuals to the repo.
Question is if it should be links to the PDFs in the README or even included PDFs in the repo that are omitted in a cargo publish.
I would really welcome that as google et. al always show prelim. versions as first hits, potentially fooling users (e.g the 52840er chip had 255byte wide EDMA transfer buffers for 2/3 peripherals when in fact it really has 2^16 - 1 bytes wide transfer buffers for all peripherals (at least at release (v1.0))).
Adding just a link keeps the storage footprint of the repo low and doesn't clutter it so much, where as committing the actual file would prevent broken links in case nordic moving stuff (which they seem to do some time; didn't happen for the reference manual yet tho; afaik).
What do y'all think about this?
Including [0, 1] would up the repo size about 15 Megs.
[2] http://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.0.pdf
[1] http://infocenter.nordicsemi.com/pdf/nRF52832_PS_v1.4.pdf
It does not have any way of changing its fields, and the only way to create an instance is via Default::default()
, so all the Resolution
, Oversample
, ... settings are impossible to use, unless I'm missing something.
Hey, I was doing some work with short EasyDMA TWIM transactions, and noticed that certain operations failed in release (opt level 3), but not in debug (opt level 0). Furthermore, they worked in opt levels 0, 1, or 'z', but not in opt level 2 or 3.
I believe this is due to the compiler not "understanding" our use of giving buffers as .ptr()
s, and assuming that certain data is never used.
I was able to fix this by placing a compiler fence (compiler_fence(Ordering::AcqRel);
after the DMA transaction was completed. It is likely we will need to use this everywhere EasyDMA is used.
the maxcnt
register in the SPI hardware is 8 bits wide on the nrf52382 but wider on the 52840. The boundary checking code currently constrains the maximum buffer size to 8 bit values which is safe but arbitrarily limiting on the 52840.
Come up with a reasonable way to express this range check that allows taking maximum advantage for the different target devices.
We're probably due up for a new release, as the Instance
changes have not been released yet.
CC #122.
Are there any other changes we would like to land before the next release?
Must do:
Could do:
nrf52-hal
/nrf52-hal-common
, maybe to nrf-hal
and nrf-hal-common
, CC #113Do we have any other (potentially breaking) changes we would like to land soon?
CC @nrf-rs/nrf52 crew
I'd suggest we aim for a release next weekend (I have some time on a train next Saturday, so I'd be up to take the lead on this).
This issue was first opened in the old nrf52-hal repository. Original discussion: jamesmunns/nrf52-hal#14
The nRF52832's DMA channels are limited to buffers with a maximum length of 255 bytes. This is very limiting. For example, in the DW1000 driver, I need to support registers that are much longer than that (although there are ways to read/write subsets).
There is a way to use multiple consecutive buffers to circumvent this limitation. The product specification alludes to this (see section 10.1), but doesn't really explain how this works. I found the following discussions that provide a clearer picture:
Since this technique requires additional system resources (PPI, TIMER) and applies to all DMA channels, I think it's probably best to provide this as a separate layer that builds on top of DMA users like SPIM.
Rng
implements CryptoRng
without turning on the bias correction. This is a bad idea since its output is not guaranteed to be uniformly distributed without doing that.
While working on the 840, I realized:
I should be able to submit fixes for this, though I'm not sure if any of the other targets support SPIM3 as well.
This issue was first opened in the old nrf52-hal repository. Original discussion: jamesmunns/nrf52-hal#10
I didn't initially implement embedded-hal traits for the new TIMER peripheral API, as embedded-hal only has a CountDown
trait, while TIMER counts up. Now that I looked into it, I don't think this is a problem, as there's no method to read back the timer value in the CountDown
trait.
From the embedded-hal documentation:
Note that the implementer doesn't necessarily have to be a downcounting timer; it could also be an upcounting timer as long as the above contract is upheld.
So it looks like the trait can be implemented.
I finally figured out why I have been having issues testing the radio functionality on my nRF51 dongle, the chip on here is old enough to be hit by "PAN 26. System: Manual setup is required to enable use of peripherals".
I wonder if applying workarounds for PAN should be done as part of the rt
feature of nrf51
? Somehow injecting a before-main function similar to the SystemInit
from the SDK.
I'm a big fan of keeping things neat and tidy, and while there's a good argument to be made that all HAL-related crates should remain in this repository, I think we should maintain board support crates in a separate repository. I believe this would have the following advantages:
adafruit_nrf52pro
crate. Currently it's pretty well-hidden in this repository.The current timer APIs unconditionally enable the compare0_stop
shortcut:
If this would be made configurable via a type parameter, Timer
could provide a Periodic
timer as well as the current one-shot implementation.
See #44 - do the same for different nrf52840 variants.
Some use cases require switching a pin between output and floating mode on the fly. This is very inconvenient with the current API. The DWM1001 board support crate has an example that demonstrates this.
I believe the solution for this is to add a tri-state mode that implements the following trait:
pub trait TriStatePin {
fn set_high(&mut self);
fn set_low(&mut self);
fn set_floating(&mut self);
}
Such an abstraction has been proposed before.
If we decide to implement this, we should submit the trait I suggested above to embedded-hal.
This issue was first opened in the old nrf52-hal repository. Original discussion: jamesmunns/nrf52-hal#11
I didn't do this initially, because I'm not sure whether it's possible, or if it is, if it should be done without modifying embedded-hal first. The problem is that the embedded-hal trait for SPI is very basic, reading and writing only single words. But SPIM supports DMA natively. The most straight-forward way to use it is to actually let it handle the whole SPI transaction.
I now discovered that there are higher-level SPI traits, but those have problems, too. Transfer uses the same buffer for sending and receiving. I'm not sure if this can be implemented for SPIM.
Maybe my doubts are unfounded and there is a reasonable way to implement those traits. Maybe the embedded-hal traits need to be changed. I'm pretty sure there's discussion about SPI somewhere on the embedded-hal issue tracker that might need to be consulted.
I looked at implementing embedded-hal Serial traits for UARTE, but it wasn't immediately obvious how we might do that. All of my implementations so far have been with a hardware FIFO and so writing byte by byte makes sense. Sending a string of 100 bytes as 100 single-byte DMA operations would clearly be sub-optimal.
Has anyone given this any thought? Does it need to just wait for the interrupt-driven UARTE driver?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.