Skip to content

v1.0.0-beta.1

Compare
Choose a tag to compare
@MabezDev MabezDev released this 03 Jun 14:16
· 182 commits to main since this release
3cd3606

To view all the documentation for all crates, along with their chip specific APIs, visit https://docs.espressif.com/projects/rust/.

Please note that only changes to the esp-hal package are tracked in these release notes, please check the esp-hal repo for other packages release notes.

Migration Guide from v1.0.0-beta.0 to 1.0.0-beta.1

Peripheral singleton changes

As this is a conceptual change, we'll not list all affected types in this section. AnyPeripheral
refers to all Any* types at the same time - AnySpi, AnyUart, etc. Similarly, Driver refers
to any matching peripheral driver.

Peripheral singletons (like SPI2 or GpioPin) no longer implement Peripheral. The Peripheral
trait and PeripheralRef struct have been removed. The peripheral singletons instead have a
lifetime and implement the following methods:

  • steal and clone_unchecked to unsafely create them.
  • reborrow to safely create a copy with a shorter lifetime.
  • degrade has been removed in favour of AnyPeripheral::from.

Application-facing changes

Peripheral drivers no longer accept &mut singleton.

Use reborrow instead:

-let driver = Driver::new(&mut peripheral);
+let driver = Driver::new(peripheral.reborrow());

After dropping the driver, peripheral should be accessible again as it used to be previously.

Peripheral driver changes

The Peripheral and PeripheralRef types no longer exist. The driver structs and constructors need
to be updated accordingly:

If the driver works with a single peripheral instance, for example AES:

 struct Driver<'d> {
-   aes: PeripheralRef<'d, AES>,
+   aes: AES<'d>,
 }
 // ...
-fn new(aes: impl Peripheral<P = AES> + 'd)
+fn new(aes: AES<'d>)

If a driver works with multiple peripheral instances, e.g. SPI:

 struct Driver<'d> {
-   spi: PeripheralRef<'d, AnySpi>,
+   spi: AnySpi<'d>,
 }
 // ...
-fn new(spi: impl Peripheral<P = impl Instance> + 'd)
+fn new(spi: impl Instance + Into<AnySpi<'d>>)

DMA changes

DMA channel types are now consistent with other peripheral singletons

For compatibility with third party libraries, as well as for consistency with other peripherals,
the DMA channel types (e.g. DmaChannel0/Spi2DmaChannel) have been replaced by
esp_hal::peripherals::DMA_channel<'d> types.

-use esp_hal::gpio::DmaChannel0;
+use esp_hal::peripherals::DMA_CH0;
-use esp_hal::gpio::Spi2DmaChannel;
+use esp_hal::peripherals::DMA_SPI2;

GPIO changes

GPIO pins are now consistent with other peripheral singletons

For compatibility with third party libraries, as well as for consistency with other peripherals,
the GPIO pin types (GpioPin<N>) have been replaced by separate esp_hal::peripherals::GPION<'d>
types.

-use esp_hal::gpio::GpioPin;
+use esp_hal::peripherals::{GPIO2, GPIO3};

-fn my_function(gpio2: GpioPin<2>, gpio3: GpioPin<3>) {...}
+fn my_function(gpio2: GPIO2<'_>, gpio3: GPIO3<'_>) {...}

GPIO matrix (interconnect) has been reworked

The GPIO matrix implementation has been reworked to solve known issues. The following changes have
been made:

  • InputConnection and OutputConnection have been removed and their functionality merged into InputSignal and OutputSignal.
  • The InputSignal and OutputSignal types now have a lifetime. This lifetime prevents them to be live for longer than the GPIO that was used to create them.
  • Because InputSignal and OutputSignal can now represent constant levels, the number method now returns Option<u8>.
  • The way to invert inputs and outputs has been changed:
    • InputSignal::inverted has been renamed to InputSignal::with_input_inverter.
    • OutputSignal::inverted has been renamed to OutputSignal::with_output_inverter.
    • InputSignal::invert and OutputSignal::invert have been removed.
    • OutputSignal now has an inverted_input property, which can be changed by using with_output_inverter.
    • The signals have is_{input, output}_inverted methods to read the state that will be used when configuring the hardware.
  • Users can now force a signal through the GPIO matrix.
  • The enable_input and enable_output methods have been renamed to set_input_enable and set_output_enable.
  • A new PeripheralSignal trait has been added, which allows us to no longer imply PeripheralInput for PeripheralOutput types.
  • Functions that accept PeripheralInput no longer accept PeripheralOutput implementations.
  • Removed Input::into_peripheral_output and Output::peripheral_input functions. The drivers can be converted into Flex which offers both ways to acquire signal types, and more.
  • Various "unreasonable" signal conversions have been removed. OutputSignal can no longer be converted into InputSignal.
  • InputSignal and OutputSignal now have a "frozen" state. If they are created by a pin driver, they start frozen. If they are created by splitting a GPIO pin, they start unfrozen. Frozen signals will not be configured by peripheral drivers.
  • Splitting GPIO pins into signals is now unsafe.
  • Flex can now be (unsafely) split into Input and Output drivers with split_into_drivers.
  • Converting AnyPin into signals will now reset the pin's configuration. Creating an InputSignal will now enable the pin's input buffer.

Flex API surface has been simplified

The enable_input method has been renamed to set_input_enable.

The Flex driver no longer provides the following functions:

  • set_as_input
  • set_as_output
  • set_drive_strength
  • set_as_open_drain
  • pull_direction

The individual configurations can be set via apply_input_config and apply_output_config.
The input buffer and output driver can be separately enabled via set_input_enable and
set_output_enable.

Normally you only need to configure your pin once, after which changing modes can be done by calling
set_input_enable and/or set_output_enable.

- flex.set_as_input(pull_direction);
+ flex.apply_input_config(&InputConfig::default().with_pull(pull_direction)); // only if needed
+ flex.set_output_enable(false);
+ flex.set_input_enable(true);

- flex.set_as_output(); // or set_as_open_drain(pull_direction)
+ flex.apply_output_config(&OutputConfig::default().with_drive_mode(open_drain_or_push_pull)); // only if needed
+ flex.set_input_enable(false); // optional
+ flex.set_level(initial_level); // optional
+ flex.set_output_enable(true);

Interrupt handling changes

The interrupt status bits are no longer cleared automatically. Depending on your use case, you will
need to either do this yourself, or disable the pin's interrupt.

If you want your interrupt to keep firing, clear the interrupt status. Keep in mind that
this affects is_interrupt_set.

 #[handler]
 pub fn interrupt_handler() {
     critical_section::with(|cs| {
         let pin = INPUT_PIN.borrow_ref_mut(cs).as_mut().unwrap();
+        pin.clear_interrupt();
     });
 }

If you want your interrupt to fire once per listen call, disable the interrupt.

 #[handler]
 pub fn interrupt_handler() {
     critical_section::with(|cs| {
         let pin = INPUT_PIN.borrow_ref_mut(cs).as_mut().unwrap();
+        pin.unlisten();
     });
 }

I2S driver now takes DmaDescriptors later in construction

  let i2s = I2s::new(
      peripherals.I2S0,
      Standard::Philips,
      DataFormat::Data16Channel16,
      Rate::from_hz(44100),
      dma_channel,
-     rx_descriptors,
-     tx_descriptors,
  );

  let i2s_tx = i2s
      .i2s_tx
      .with_bclk(peripherals.GPIO2)
      .with_ws(peripherals.GPIO4)
      .with_dout(peripherals.GPIO5)
-     .build();
+     .build(tx_descriptors);

  let i2s_rx = i2s
      .i2s_rx
      .with_bclk(peripherals.GPIO2)
      .with_ws(peripherals.GPIO4)
      .with_din(peripherals.GPIO5)
-     .build();
+     .build(rx_descriptors);

PARL IO driver changes

ParlIoFullDuplex, ParlIoTxOnly and ParlIoRxOnly have been merged into ParlIo

- let parl_io = ParlIoFullDuplex::new(peripherals.PARL_IO, dma_channel)?;
- let parl_io = ParlIoTxOnly::new(peripherals.PARL_IO, dma_channel)?;
- let parl_io = ParlIoRxOnly::new(peripherals.PARL_IO, dma_channel)?;
+ let parl_io = ParlIo::new(peripherals.PARL_IO, dma_channel)?;

Construction no longer asks for references

 let mut parl_io_tx = parl_io
     .tx
     .with_config(
-        &mut pin_conf,
-        &mut clock_pin,
+        pin_conf,
+        clock_pin,
         0,
         SampleEdge::Normal,
         BitPackOrder::Msb,
     )?;

Construction options are passed via config

+let config = RxConfig::default()
+                 .with_frequency(Rate::from_mhz(20))
+                 .with_bit_order(BitPackOrder::Msb);

 let mut parl_io_rx = parl_io
     .rx
     .with_config(
         pin_conf,
         clock_pin,
-        BitPackOrder::Msb,
-        None,
+        config,
     )?;
+let config = TxConfig::default()
+                 .with_frequency(Rate::from_mhz(20))
+                 .with_sample_edge(SampleEdge::Normal)
+                 .with_bit_order(BitPackOrder::Msb);

 let mut parl_io_tx = parl_io
     .tx
     .with_config(
         pin_conf,
         clock_pin,
-        0,
-        SampleEdge::Normal,
-        BitPackOrder::Msb,
+        config,
     )?;

SPI Slave driver now uses the newer DMA APIs

  let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000);
+ let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
+ let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();

- let transfer = spi.transfer(&mut rx_buffer, &mut tx_buffer)?;
+ let transfer = spi.transfer(dma_rx_buf.len(), dma_rx_buf, dma_tx_buf.len(), dma_tx_buf)?;

- let transfer = spi.write(&mut tx_buffer)?;
+ let transfer = spi.write(dma_tx_buf.len(), dma_tx_buf)?;

- let transfer = spi.read(&mut rx_buffer)?;
+ let transfer = spi.read(dma_rx_buf.len(), dma_rx_buf)?;

DMA memcpy driver now uses the newer DMA APIs

  let mut mem2mem = Mem2Mem::new(
      peripherals.DMA_CH0,
      dma_peripheral,
+ ).with_descriptors(
      rx_descriptors,
      tx_descriptors,
+     BurstConfig::default(),
  ).unwrap();

LCD_CAM Camera changes

The data and ctrl pins of the camera have been split out into individual with_* methods.

- camera.with_ctrl_pins(vsync_pin, href_pin);
+ camera.with_vsync(vsync_pin).with_h_enable(href_pin);
+ config.with_vh_de_mode(VhdeMode::VsyncHsync);
- camera.with_ctrl_pins_and_de(vsync_pin, hsync_pin, href_pin);
+ camera.with_vsync(vsync_pin).with_hsync(hsync_pin).with_h_enable(href_pin);
+ config.with_vh_de_mode(VhdeMode::De); // Needed to enable HSYNC pin
- let data_pins = RxEightBits::new(
-     peripherals.GPIO11,
-     peripherals.GPIO9,
-     peripherals.GPIO8,
-     ....
- );
  let mut camera = Camera::new(
      lcd_cam.cam,
      peripherals.DMA_CH0,
-     data_pins,
-     config,
+     config.with_enable_2byte_mode(false) // If you were previously using RxEightBits (This is the default)
+     config.with_enable_2byte_mode(true) // If you were previously using RxSixteenBits
  )?;

+ camera.with_data0(peripherals.GPIO11).with_data1(peripherals.GPIO9).with_dataX();

SPI changes

Spi::transfer no longer returns the input buffer.

-let received = spi.transfer(&mut data[..]).unwrap();
-work_with(received);
+spi.transfer(&mut data[..]).unwrap();
+work_with(&data[..]);

Configuration changes

Some configuration options are now unstable and they require the unstable feature to be
enabled. You can learn about a particular option in the esp-hal documentation.

The ESP_HAL_CONFIG_PLACE_SPI_DRIVER_IN_RAM configuration option has been renamed to ESP_HAL_CONFIG_PLACE_SPI_MASTER_DRIVER_IN_RAM.

Changes related to cargo features

The log feature has been replaced by log-04.
The following dependencies are now gated behind the unstable feature and their
invididual features are no longer available:

  • digest
  • ufmt-write

The usb_otg and bluetooth features are now considered private and have been renamed accordingly.

The debug feature has been removed. If you used it, enable impl-register-debug on the PAC of your device.