GithubHelp home page GithubHelp logo

rp-rs / rp-hal Goto Github PK

View Code? Open in Web Editor NEW
1.3K 22.0 222.0 1.95 MB

A Rust Embedded-HAL for the rp series microcontrollers

Home Page: https://crates.io/crates/rp2040-hal

Rust 99.93% Batchfile 0.03% Shell 0.04%

rp-hal's Introduction


Logo

rp-hal

Rust support for the "Raspberry Silicon" family of microcontrollers
Explore the API docs »

View Demos · Report a Bug · Chat on Matrix

Table of Contents

  1. Getting Started
  2. Programming
  3. Roadmap
  4. Contributing
  5. License
  6. Contact
  7. Acknowledgements

Getting Started

So, you want to program your new Raspberry Silicon microcontroller, using the Rust programming language. You've come to the right place!

This repository is rp-hal - a collection of high-level drivers for the Raspberry Silicon RP2040 microcontroller and various associated boards, like the Raspberry Pi Pico and the Adafruit Feather RP2040.

If you want to write an application for Raspberry Silicon, check out our RP2040 Project Template.

If you want to write code that uses the Raspberry Silicon PIO State Machines, check out pio-rs. You can even compile PIO programs at run-time, on the RP2040 itself!

If you want to try out some examples on one of our supported boards, check out the list of Board Support Packages, and click through to see the various examples for each board.

Before trying any of the examples, please ensure you have the latest stable version of Rust installed, along with the right target support:

rustup self update
rustup update stable
rustup target add thumbv6m-none-eabi

You may also want to install these helpful tools:

# Useful to creating UF2 images for the RP2040 USB Bootloader
cargo install elf2uf2-rs --locked
# Useful for flashing over the SWD pins using a supported JTAG probe
cargo install --locked probe-rs-tools

Packages

There is a Hardware Abstraction Layer (or HAL) crate for the RP2040 chip, and Board Support Package crates for a number of RP2040 based PCBs. If you are writing code that should run on any microcontroller, consider using the generic Rust Embedded Working Group's Embedded HAL.

If you are writing code that should work on any RP2040 device, use the HAL crate. If you are running code on a specific board, use the appropriate BSP crate (which will include the HAL crate for you). Please note, you cannot depend on multiple BSP crates; you have to pick one, or use Cargo Features to select one at build time.

Each BSP includes some examples to show off the features of that particular board.

You should include this crate in your project if you want to write a driver or library that runs on the Raspberry Silicon RP2040, or if you are writing a Board Support Package (see later on).

The crate provides high-level drivers for the RP2040's internal peripherals, such as the SPI Controller and the I²C Controller. It doesn't know anything about how your particular board is wired up (such as what each IO pin of the RP2040 is connected to).

There are examples in this crate to show how to use various peripherals (GPIO, I²C, SPI, UART, etc) but note that the pin-outs may not match any particular board.

BSPs - Board support packages

There are BSPs for various boards based on the RP2040 available in a separate repository.

Programming

Rust generates standard Arm ELF files, which you can load onto your Raspberry Pi Silicon device with your favourite Arm flashing/debugging tool. In addition, the RP2040 contains a ROM bootloader which appears as a Mass Storage Device over USB that accepts UF2 format images. You can use the elf2uf2-rs package to convert the Arm ELF file to a UF2 format image.

For boards with USB Device support like the Raspberry Pi Pico, we recommend you use the UF2 process.

The RP2040 contains two Cortex-M0+ processors, which execute Thumb-2 encoded ARMv6-M instructions. There are no operating-specific features in the binaries produced - they are for 'bare-metal' systems. For compatibility with other Arm code (e.g. as produced by GCC), Rust uses the Arm Embedded-Application Binary Interface standard or EABI. Therefore, any Rust code for the RP2040 should be compiled with the target thumbv6m-none-eabi.

More details can be found in the Project Template.

Linker flags

Besides the correct target, which mainly defines the instruction set, it's also necessary to use a certain memory layout compatible with the rp2040. To achieve that, rustc must be called with appropriate linker flags. In the Project Template, those flags are defined in .cargo/config.toml. Another necessary file is memory.x.

More detailed information on how the linker flags work can be found in the cortex_m_rt docs.

In most cases, it should be sufficient to use the example files from the Project Template.

Loading a UF2 over USB

Step 1 - Install elf2uf2-rs:

$ cargo install elf2uf2-rs --locked

Step 2 - Make sure your .cargo/config contains the following (it should by default if you are working in this repository):

[target.thumbv6m-none-eabi]
runner = "elf2uf2-rs -d"

The thumbv6m-none-eabi target may be replaced by the all-Arm wildcard 'cfg(all(target_arch = "arm", target_os = "none"))'.

Step 3 - Boot your RP2040 into "USB Bootloader mode", typically by rebooting whilst holding some kind of "Boot Select" button. On Linux, you will also need to 'mount' the device, like you would a USB Thumb Drive.

Step 4 - Use cargo run, which will compile the code and started the specified 'runner'. As the 'runner' is the elf2uf2-rs tool, it will build a UF2 file and copy it to your RP2040.

$ cargo run --release --features "critical-section-impl,rt,defmt" --example pwm_blink

(The pwm_blink example doesn't need all these feature flags. They are listed here so you can use the same command for all examples.)

Loading with probe-rs

probe-rs is a library and a command-line tool which can flash a wide variety of microcontrollers using a wide variety of debug/JTAG probes. Unlike using, say, OpenOCD, probe-rs can autodetect your debug probe, which can make it easier to use.

Step 1 - Install probe-rs:

$ cargo install --locked probe-rs-tools

Alternatively, follow the installation instructions on https://probe.rs/.

Step 2 - Make sure your .cargo/config contains the following:

[target.thumbv6m-none-eabi]
runner = "probe-rs run --chip RP2040"

Step 3 - Connect your USB JTAG/debug probe (such as a Raspberry Pi Pico running this firmware) to the SWD programming pins on your RP2040 board. Check the probe has been found by running:

$ probe-rs list
The following debug probes were found:
[0]: J-Link (J-Link) (VID: 1366, PID: 0101, Serial: 000099999999, JLink)

There is a SEGGER J-Link connected in the example above - the message you see will reflect the probe you have connected.

Step 4 - Use cargo run, which will compile the code and start the specified 'runner'. As the 'runner' is the probe-rs tool, it will connect to the RP2040 via the first probe it finds, and install your firmware into the Flash connected to the RP2040.

$ cargo run --release --example pwm_blink

Loading with picotool

As ELF files produced by compiling Rust code are completely compatible with ELF files produced by compiling C or C++ code, you can also use the Raspberry Pi tool picotool. The only thing to be aware of is that picotool expects your ELF files to have a .elf extension, and by default Rust does not give the ELF files any extension. You can fix this by simply renaming the file.

Also of note is that the special pico-sdk macros which hide information in the ELF file in a way that picotool info can read it out, are not supported in Rust. An alternative is TBC.

Roadmap

NOTE These packages are under active development. As such, it is likely to remain volatile until a 1.0.0 release.

See the open issues for a list of proposed features (and known issues).

Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.

The steps are:

  1. Fork the Project by clicking the 'Fork' button at the top of the page.
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Make some changes to the code or documentation.
  4. Commit your Changes (git commit -m 'Add some AmazingFeature')
  5. Push to the Feature Branch (git push origin feature/AmazingFeature)
  6. Create a New Pull Request
  7. An admin will review the Pull Request and discuss any changes that may be required.
  8. Once everyone is happy, the Pull Request can be merged by an admin, and your work is part of our project!

Code of Conduct

Contribution to this crate is organized under the terms of the Rust Code of Conduct, and the maintainer of this crate, the rp-rs team, promises to intervene to uphold that code of conduct.

License

The contents of this repository are dual-licensed under the MIT OR Apache 2.0 License. That means you can choose either the MIT license or the Apache-2.0 license when you re-use this code. See MIT or APACHE2.0 for more information on each specific license.

Any submissions to this project (e.g. as Pull Requests) must be made available under these terms.

Contact

Raise an issue: https://github.com/rp-rs/rp-hal/issues Chat to us on Matrix: #rp-rs:matrix.org

Acknowledgements

rp-hal's People

Contributors

9names avatar akiyukiokayasu avatar anall avatar andrewh42 avatar archusr64 avatar asaffisher avatar contradict avatar devsnek avatar eolder avatar gip-gip avatar hardiesoft avatar hmvp avatar ithinuel avatar jannic avatar jenntoo avatar jlpettersson avatar jonathanpallant avatar jonil avatar jsgf avatar liamolucko avatar mgottschlag avatar nashenas88 avatar nelsonapenn avatar nic0w avatar nilclass avatar sizurka avatar thejpster avatar tommy-gilligan avatar victorkoenders avatar weirdconstructor 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

rp-hal's Issues

Clocks improvements

Collected suggested improvements from #31:

  • Rename selfaux_source macro. See: #31 (comment)
  • Better name/handling around aux sources and glitchless mux: See discussion: #31 (comment)
    • Better name for set_self_aux_src
    • Possibly: Prevent aux-aux transition while the aux source is active on the clocks with glitchless muxes. (Per datasheet: clock glitches on these should be avoided at all costs as the CPU or other important logic is possibly currently running off of the clock.)
    • Possibly: Prevent clock source switches on a running clock w/o the glitchless mux. (Per datasheet: disable the clock, wait 2 cycles of source clock, switch the (aux) source, re-enable clock, wait 2 clock cycles of new source)
  • await_select is a bit of a pain from a user perspective, as it requires knowing the internal clock number. Clock source switches probably should return a type that you can call await on. See: #31 (comment)

Add a blinky example using the HAL

Can be implemented after the following parts have been implemented:

  • GPIO (#4)
  • Resets
  • Clocks (#6)

Use cases:

  • Starting point for fresh projects
  • Getting a quick overview of the HAL

HAL tracking issue

This issue should make it easier to get a quick overview on what parts of the chip are being worked on.

HAL

The hardware abstraction layer (HAL) provides ergonomic access to the peripherals of the RP2040 chip (e.g. UART, USB, GPIOs).

A peripheral that is not yet supported in the HAL can still be used with the peripheral access crate (PAC). It provides access to the raw registers which can then be used as described in the RP2040 datasheet.

Not yet available

  • CPU
    • Sysinfo
  • Peripherals
    • SSI

Basic support

Needs docs / examples

  • Clocks and Resets

BSPs

A board support package allows easy setup of peripherals of a given board. It provides for example the clock frequency used on that board. Or it can provide named pins that match the markings and components of that board.
Note: all boards found so far use a 12Mhz crystal (XTAL), the built-in bootloader will not function with a different XTAL

Not yet available

Supported

UART example

Hi,

Can anyone provide example for setting up UART?
I'm having issue that I located (using led) to be in UartPeripheral::enable (code probably panics or hangs the cpu)
I located that it cannot be invalid frequency (as I didn't unwrap error) and I didn't found anything obvious inside that could cause that.

Thanks

Support for hardware divider and firmware float support

Thinking about the benefits of switching to rust from c/c++ for the pico, a few basic things stand out as downsides to rust. The C/C++ SDK links the standard / and % operators to the onboard hardware divider. Im not 100% sure on the internals of the rust arm compiler and the HAL/PAC for the rp2040 but assumedly, unless manually implemented, the rust compiler will not be able to correctly use the hardware divider. This is most definitely the same with the firmware float implementations. Both of these additions would let rust programs be able to fully take over the full power of the rp2040 chip that currently is exclusive to the standard C/C++ SDK and Micropython implementation.

USB enumeration errata

The current USB implementation does not handle RP2040-E5.
The description of the errata from the datasheet is as follows:

USB device fails to exit RESET state on busy USB bus

The USB bus RESET state is triggered by the host sending SE0 for 10ms to the device. The USB device
controller requires 800μs of idle ( J-state ) after a bus reset before moving to the CONNECTED state. Without
this idle time, the USB device does not connect and will not receive any packets from the host, and so
does not enumerate.

A device reset happens just after the device is plugged in. Although a host will wait before talking to a
reset device, other devices attached to the same USB hub may also be communicating with the host.
USB 2.0 and USB 3.0 hubs have one or more transaction translators, which facilitate low speed and full
speed transactions on a higher speed bus. It depends on the hub design, but a transaction translator is
usually shared between a few ports.

As the RP2040 USB device is full speed, its traffic when connected to a hub will come via a transaction
translator. This means that if you have another device plugged in next to an RP2040, the RP2040 is likely
to see some messages from the host addressed to the other device. If the device is not very active, for
example, a mouse that is polled every 8ms, this is not a problem. However some devices, such as a USB
serial port, are polled every 30-50μs. In this case the bus is very active, and will cause the RP2040 to never
exit RESET state and not connect.

There is a software workaround for this issue (see workaround section). A user can also work around this
by closing the USB serial port or any other offending devices while connecting their RP2040 and then re
opening their USB serial port.

On a larger hub, the problem may be fixed by moving the RP2040 far away (onto a different transaction
translator) from the offending device. For example, connecting the RP2040 to port 1 of a 7 port hub, and
connecting the USB serial console to port 7, may solve the issue. Connecting the RP2040 to a separate
USB hub to any busy devices will also fix the problem.

Workaround

Use software to force USB device controller to see idle USB bus for 800μs to move the device from the
RESET state to the CONNECTED state. This fix uses internal debug logic that is connected to GPIO15 for a short
amount of time (~800μs). This forces the controller to see DP as a logical 1 (and DM and logical 0) to
make the USB Device controller believe there is a J-state on the USB bus. GPIO15 does not need to be tied
in any particular way for this fix to work. Instead, we can force the input path in software using the Section
2.19 input override feature. See https://github.com/raspberrypi/pico-sdk/tree/master/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/rp2040_usb_device_enumeration.c.

BSPs should handle rp2040_boot2

We're currently manually specifying which boot2 to use inside user/example code.
If the BSP exported a bootloader symbol, BSP examples could be generic.
Example

// alias for the bsp so we don't have to change as much code when changing targets
use feather_rp2040 as target_bsp;
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = target_bsp::BOOT_LOADER;

instead of a different

pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GD25Q64CS;

for each board

Example for SPI

We have usage of SPI in the BSP for pico_explorer.

let dc = internal_pins.spi_miso.into_push_pull_output();
let cs = internal_pins.lcd_cs.into_push_pull_output();
let spi_sclk = internal_pins.spi_sclk.into_mode::<FunctionSpi>();
let spi_mosi = internal_pins.spi_mosi.into_mode::<FunctionSpi>();
let spi_screen = Spi::<_, _, 8>::new(spi0).init(
resets,
125_000_000u32.Hz(),
16_000_000u32.Hz(),
&MODE_0,
);
let spii_screen = SPIInterface::new(spi_screen, dc, cs);
let mut screen = ST7789::new(spii_screen, DummyPin, 240, 240);
screen.init(delay).unwrap();
screen
.set_orientation(st7789::Orientation::Portrait)
.unwrap();
screen.clear(Rgb565::BLACK).unwrap();

We need to make a standalone example for this peripheral.

Add RTIC Example

I have started trying to use RTIC v0.6.x with this hal with limited success. It would be great to have an example using RTIC with an external interrupt.

If someone has already done this in another project I would be happy to write the example, but my current work is failing.

memory.x only included by accident

memory.x is only included by an INCLUDE memory.x line in the cortex-m-rt link.x file. Because we don't copy the file to ./target, the file is effectively only included by accident and only if you happen to be in the root of the git repo when you do the build.

Also, the sections are out of order which breaks raspberrypi/picotool#39

Allow setup of the clocks block

The clock systems are described in chapter 1.15 of the datasheet.

Use cases

The clock block provides clocks to all parts of the SoC. Thus it defines how much time equals one clock cycle for different parts of the chip.

Clock sources

  • Ring Oscilator (ROSC, chapter 2.17)
  • Crystal Oscilator (XOSC, chapter 2.16)
  • USB- and System-PLL (referencing XOSC, chapter 2.18)
  • External GPIO

Switching clock sources

Clock glitches need to be avoided when changing the clock source, see chapter 2.15.3.2.

Also changing the clock speed will affect all connected components. E. g. halfing the divider for clk_peri would double the baud rate of a running UART.

Implementation ideas

  • Allow freezeing the clock speed. This should consume the clock path so it can not be changed while a device is using it. Example: stm32f30x-hal, also this blog article. But maybe there should be a way to get back control over the clock speeds.
  • Peripherals (e.g. UART) should be able to take the correct clock setting (maybe defined via the type) to be used when setting up e.g. baudrates.
  • Another example: stm32h7xx-hal docs.rs
  • Crate for durations and rate: embedded-time

Mockup

let p = rp2040::peripherals.take();
let mut resets = p.RESET;

let xosc = p.XOSC.with_osc(12.mhz());

let sys_pll = p.SYS_PLL
    .input(xosc)
    .output(125.mhz())
    .freeze();

let clk_peri = p.CLK_PERI
    .source(sys_pll.clone()) // Switching source() should be done with all the needed ceremony against glitches
    .divide_by(42)
    .enable()
    .freeze(); 

let uart = p.UART0
    .enable(&mut resets) // Lift reset and wait for ack, see chapter 2.14
    .clk(clk_peri)
    .baudrate(9600)
    .finish();
uart.write_all("Hello world!");

Hardware Divider/Modulo support

See section 2.3.1.5 of the reference manual for more info on this peripheral.

This is part of the SIO peripheral, and may require use of a mutex or the hardware spinlocks provided by the SIO to use safely. In the initial implementation, having it block until complete would be recommended.
You can also assume (for the initial implementation) that it's never used by interrupts or by the 2nd core.

Minimum deliverable should be standalone function(s) with examples that demonstrate that results match built-in / and % operators.

Issues when setting bits in registers

In pwm.rs I saw:

pad.gpio[self.pin].write(|w| w.ie().set_bit());
pad.gpio[self.pin].write(|w| w.od().clear_bit());

My understanding of write is that it does:

let w = register.defaults();
let w = closure(w);
register.set_bits(w);

So the second line (clearing od) will undo the effects of the first. This should probably be:

pad.gpio[self.pin].modify(|_r, w| {
    w.ie.set_bit();
    w.od.clear_bit();
    w
});

SPI support

There are two SPI interfaces described in section 4.4 of the datasheet

Both interfaces support:

  • Master or slave mode
  • Programmable clock and word size
  • Programmable choice of GPIO pins
  • Separate transmit, receive, overflow and receive timeout interrupts

Improve i2c error handling

In the current i2c implementation there are several asserts relating to buffer sizes, invalid addresses.

assert!(bytes.len() < 256 && bytes.len() > 0);

Need to validate that these are all necessary (with appropriate testing and documentation)

Also, rather than panic at runtime these should ideally be compile-time errors, or return appropriate error types that the caller can handle.

Should the Spi new function take ownership of the spi pins?

It feels a bit weird that they are left hanging

let _spi_sclk = pins.gpio6.into_mode::<FunctionSpi>();
let _spi_mosi = pins.gpio7.into_mode::<FunctionSpi>();
let _spi_miso = pins.gpio4.into_mode::<FunctionSpi>();
let mut spi = Spi::<_, _, 8>::new(pac.SPI0).init(
    &mut pac.RESETS,
    SYS_HZ.Hz(),
    16_000_000u32.Hz(),
    &MODE_0,
);

Compare to i2c:

let sda_pin = pins.gpio18.into_mode::<FunctionI2C>();
let scl_pin = pins.gpio19.into_mode::<FunctionI2C>();

let mut i2c = I2C::i2c1(
    peripherals.I2C1,
    sda_pin,
    scl_pin,
    400.kHz(),
    &mut peripherals.RESETS,
    125_000_000.Hz(),
);

If this is desired i can implement it!

PIO

PIO is covered in chapter 3 of the datasheet.

Overview

The RP2040 has two PIOs, each with four state machines. State machines in the same PIO share instruction memory and can communicate via IRQs.

The four state machines execute from a shared instruction memory. System software loads programs into this memory, configures the state machines and IO mapping, and then sets the states machines running. [...] From this point on, state machines are generally autonomous, and system software interacts through DMA, interrupts andcontrol registers, as with other peripherals on RP2040

Implementation

Most likely a builder interface. There are a lot of options to set:

  • wrap top
  • wrap bottom
  • side en
  • side pindir
  • jmp pin
  • out sticky
  • inline out enabled
  • inline out bits
  • in base
  • out base
  • out count
  • set base
  • set count
  • sideset base
  • sideset count
  • fjoin rx
  • fjoin tx
  • autopush enabled
  • autopull enabled
  • autopush threshold
  • autopull threshold
  • out shift direction
  • in shift direction
  • clock divider

fmul crashes chip

    let fmul = hal::rom_data::fmul();
    let rom_result = fmul(x, y);

fmul has the value 0x64C on my chip. But calling the fmul function crashes my program.

Timer module support

We haven't implemented the alarms at as all, and the current counter read implementation is not thread safe (as it uses the latched registers, which could race).
It needs to be changed to use the raw read registers and check for overflow like the C SDK and embassy-rp

Watchdog timer set to garbage

It looks like watchdog is configured incorrectly in init_clocks_and_plls

watchdog.enable_tick_generation(xosc_crystal_freq as u8);

in datasheet it is that it should work at 1MHz (and alarms are using the same clock), therefore this should be set here to:
(xosc_crystal_freq / 1_000_000) as u8
currently it is trying write very big number (12MHz) to 8bits and as it is truncated it sets it to garbage value

PIO example which loads a .pio file

If you are working with the Pico SDK, you might have some PIO code written out in a .pio file. We should have an example of some Rust code that can load the .pio file at compile time.

PIO sideset does not work (wrong pindir)

I tried to write a PIO program that used sideset, but sideset assignments did not have any effect. It turns out that apparently it is necessary to set the pindir of the sideset pins before using them. The documentation calls the function pio_sm_set_pindirs_with_mask() for that which takes a 32-bit bitmask and sets the pindir for all currently selected set pins according to the mask. The following code is equivalent to that function, to be placed in StateMachine:

pub fn set_pindirs_with_mask(&self, mut pins: u32, pindir: u32) {
    let mut pin = 0;
    while pins != 0 {
        if (pins & 1) != 0 {
            // Select a single "set" pin.
            self.sm().sm_pinctrl.write(|w| {
                unsafe {
                    w.set_count().bits(1);
                    w.set_base().bits(pin as u8);
                }
                w
            });
            // Execute "set pindir, <dir>", where "dir" is 1 if the pin is in the mask.
            self.sm().sm_instr.write(|w| {
                unsafe {
                    w.sm0_instr().bits(0xe080 | ((pindir >> pin) & 0x1) as u16);
                }
                w
            });
        }
        pin += 1;
        pins = pins >> 1;
    }
}

This function has the nice sideeffect that it often saves a set pindir, ... instruction at the beginning of the program.

I do not know how to properly integrate such a function into the PIO abstraction - the Pico SDK implementation just saves and restores selected pins in that function. That, however, does not work if the state machine is currently active - although, if I understand it correctly, the current PIO abstraction does not try to provide any safeguards against such misuse? Other HALs use a lot more typestates for that.

Blinky.rs doesn't work

the blinky example in rp2040-hal doesn't seem to work. the example compiled just fine. and after converting it to .uf2 and move it to a pico board, the led on pin 25 doesn't blink at all.

PIO example which loads a .hex (compile PIO asm) file

There may be cases where you are using pioasm to compile your PIO code and you want to load a compiled PIO program into your Rust code (maybe also loading the same compiled PIO program in a C program).

We should have an example on how to do that.

Add control for GPIOs

The datasheet covers GPIOs in chapter 2.19. The chips has two IO banks, bank 1 is used for the QSPI flash which could be covered separately. This issue covers IO bank 0 which can be used for general purpose IO.

Use cases

The GPIOs can be used for these functions (chapter 2.19.2):

  • Control/read pin level (SIO, chapter 2.3.1)
  • Connecting a pin to a peripheral (PIO, SPI, UART, I2C, PWM, ADC, USB Vbus control)
  • Use as an interrupt (chapter 2.19.3)

The following settings can be changed for each pin (chapter 2.19.4):

  • Output drive strength
  • Output slew rate
  • Schmitt trigger
  • Pull-up/down
  • Signal and direction inversion and override

The input buffer and output driver can be disabled (which is mandatory when used with the ADC (chapter 4.9.1)).

Implementation ideas

Type states

To make it harder to misuse we could add the following as type parameters (similar to NRF HAL and the embedded book):

  • Function selection (In-/Output (SIO), PIO[01], SPI[01]-(Rx|Tx|...), ...)
  • Pull-Up/Down (only for Inputs)

Traits

All pins have the same configurations listed above. So a trait that covers all these settings could make sense.

Interrupts

ToDo...

Missing example for PIO

Now that we've landed PIO support, we should get a basic example up and going showing how to use it.
This is separate to any other, complex examples using PIO for specific tasks too.

USB Support

USB is described in section 4.1 of the datasheet.

I've started working on USB support, with the goal of a RP2040 driver for usb-device.

Clocks/Delay papercut.

You have the system clock speed in the results of hal::clocks::init_clocks_and_plls. But you can't just pass it to cortex_m::delay::Delay. And it feels like you should be able to.

Bootrom functions

Does the bootrom table lookup code work? It's just that according to Datasheet section 2.8.3, the Bootrom stores the table addresses as 16-bit values - these need to be read as 16-bit values, then expanded to 32-bit, then converted to the appropriate pointer. I suspect the code as written will read 32-bits from the bootrom, and get thus get the pointer very wrong.

GPIO interrupt register accesses may be unsound

The pointers used to access GPIO interrupt registers are likely to be unsound (due to pointing outside of the original object).
Check if the original object in the PAC is an array, and if it isn't, convert it to an array then update src/gpio/reg.rs functions to index into it.

Originally posted by @9names in #147 (comment)

Need to update references to rp2040-boot2-rs

Currently for boards other than the Pico, rp2040-boot2-rs is referenced by a specific commit as no released version has the board specific second stage boot loader. This should be changed once the next release of rp2040-boot2-rs is available.

Consider re-exporting SPI, I2C, etc at the top-level.

Do people really need to know or care that the I2C struct lives in the rp2040-hal::i2c module? Same for the other peripheral structures.

This occurred to me as the examples seem to contain a lot of tautologies.

UART example?

It is unclear to me how to use the UART peripherals. Specifically:

  • What does the frequency parameter mean when calling UartPeripheral::enable? I cannot find anything about this online, only baud rate is mentioned.
  • What pins are used for the peripherals? The rp2040 datasheet mentions that multiple pins can be used.

For testing i hooked up what i thought were the default tx and rx pins for UART0 (GP0 and GP1 respectively) to the rx and tx pins on a raspberry pi 3. Then i ran picocom on it with the same paramers as i use on the pi pico, baudrate 9600, data bits 8, stop bits 1, and parity none. I tried with frequencies 1, 1000 and 100000. Sometimes i would get some bogus output but most of the time there was nothing.

I'm not exactly experienced with embedded development so if i'm missing something obvious, do tell me.

Current state?

Hi there,

I would be interested to help with this to learn more about Rust on embedded. However, it doesn't look like there is active progress here at the moment. Are you expectingg this project to take up activity again, or is it stalled for now?

And if I were to try to continue here. Which issue or PR should be the first thing to look into? I see there are two draft PRs. I would assume, they need more work to get merged? If so, what is missing?

Thanks 👋

readme.md files for repo and subprojects

The only readme.md in the project is in the repository root.
This file does not get published to crates.io on release of the HAL or the BSP crates.

We should move the current readme into the HAL path, and create a new one in the base of the repo that provide links to the HAL/BSPs readme.md files, as well as links to matrix channel, projects of interest and other community info.

Blinky example?

Hi all,

Keen to follow this hal. Have a few boards coming and might try to port some of my bluepill code to the rp to see how it goes (long term).

Shorter term, is there a blinky sample/example to getting started?. I suspect the rpi pico will be fairly popular, so would be good to have a guide helping people with the basics :)

I2C Support

I2C Peripheral Support:

See Chapter 4 Section 3 of the datasheet for more information.

Each I2C controller is based on a configuration of the Synopsys DW_apb_i2c (v2.01) IP. The following features are supported:
•Master or Slave (Default to Master mode)
•Standard mode, Fast mode or Fast mode plus
•Default slave address 0x055
•Supports 10-bit addressing in Master mode
•16-element transmit buffer
•16-element receive buffer
•Can be driven from DMA
•Can generate interrupts

Implementation:

Awaits #4

Running tests on CI

After merging PR #29 we started running cargo test on the CI host
This CI stage started failing on #24 with error message: Error: language item required, but not found: eh_personality
Link to CI failure https://github.com/rp-rs/rp-hal/pull/24/checks?check_run_id=2498172416

We would like to run tests that exercise embedded_hal traits, but these will not run in CI without providing them.
I could not find any other HAL attempting to run cargo test on the hosts CI, there are security/reliability issues with running HIL(hardware-in-loop) with CI on one of the developers systems, and I don't think linux-embedded-hal is sufficiently advanced that we can use it for this purpose.

My current proposal is that we stop running cargo test as part of CI until we can determine how to do so without causing more harm than good.
I've created a PR #32 that does that, as well as breaking our current CI workload into multiple workflows to aid discovery

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.