Releases: esp-rs/esp-hal
0.22.0
Please note that only changes to the esp-hal
package are tracked in these release notes.
Migration Guide
IO changes
GPIO pins are now accessible via Peripherals
let peripherals = esp_hal::init(Default::default());
-let io = Io::new(peripherals.GPIO, peripherals.IOMUX);
-let pin = io.pins.gpio5;
+let pin = peripherals.GPIO5;
Io
constructor changes
new_with_priority
andnew_no_bind_interrupts
have been removed.
Useset_priority
to configure the GPIO interrupt priority.
We no longer overwrite interrupt handlers set by user code during initialization.new
no longer takesperipherals.GPIO
Removed async
-specific constructors
The following async-specific constuctors have been removed:
configure_for_async
DMA channel constructorsTwaiConfiguration::new_async
andTwaiConfiguration::new_async_no_transceiver
I2c::new_async
LcdCam::new_async
UsbSerialJtag::new_async
Rsa::new_async
Rmt::new_async
Uart::new_async
,Uart::new_async_with_config
UartRx::new_async
,UartRx::new_async_with_config
UartTx::new_async
,UartTx::new_async_with_config
You can use the blocking counterparts, then call into_async
on the returned peripheral instead.
-let mut config = twai::TwaiConfiguration::new_async(
+let mut config = twai::TwaiConfiguration::new(
peripherals.TWAI0,
loopback_pin.peripheral_input(),
loopback_pin,
twai::BaudRate::B1000K,
TwaiMode::SelfTest,
-);
+).into_async();
Some drivers were implicitly configured to the asyncness of the DMA channel used to construct them.
This is no longer the case, and the following drivers will always be created in blocking mode:
i2s::master::I2s
spi::master::SpiDma
andspi::master::SpiDmaBus
Peripheral types are now optional
You no longer have to specify the peripheral instance in the driver's type for the following
peripherals:
- SPI (both master and slave)
- I2S
- I2C
- TWAI
- UART
-Spi<'static, SPI2, FullDuplexMode>
+Spi<'static, FullDuplexMode>
-SpiDma<'static, SPI2, HalfDuplexMode, Blocking>
+SpiDma<'static, HalfDuplexMode, Blocking>
-I2sTx<'static, I2S0, Async>
+I2sTx<'static, Async>
Note that you may still specify the instance if you need to. To do this, we provide _typed
versions of the constructors (for example: new_typed
, new_half_duplex_typed
). Please note that
the peripheral instance has been moved to the last generic parameter position.
let spi: Spi<'static, FullDuplexMode, SPI2> = Spi::new_typed(peripherals.SPI2, 1.MHz(), SpiMode::Mode0);
I2C changes
The I2C master driver and related types have been moved to esp_hal::i2c::master
.
The with_timeout
constructors have been removed. new
and new_typed
now take a Config
struct
with the available configuration options.
- The default configuration is now:
- bus frequency: 100 kHz
- timeout: about 10 bus clock cycles
The constructors no longer take pins. Use with_sda
and with_scl
instead.
-use esp_hal::i2c::I2c;
+use esp_hal::i2c::{Config, I2c};
-let i2c = I2c::new_with_timeout(peripherals.I2C0, io.pins.gpio4, io.pins.gpio5, 100.kHz(), timeout);
+I2c::new_with_config(
+ peripherals.I2C0,
+ {
+ let mut config = Config::default();
+ config.frequency = 100.kHz();
+ config.timeout = timeout;
+ config
+ },
+)
+.with_sda(io.pins.gpio4)
+.with_scl(io.pins.gpio5);
The calculation of I2C timeout has changed
Previously, I2C timeouts were counted in increments of I2C peripheral clock cycles. This meant that
the configure value meant different lengths of time depending on the device. With this update, the
I2C configuration now expects the timeout value in number of bus clock cycles, which is consistent
between devices.
ESP32 and ESP32-S2 use an exact number of clock cycles for its timeout. Other MCUs, however, use
the 2^timeout
value internally, and the HAL rounds up the timeout to the next appropriate value.
Changes to half-duplex SPI
The HalfDuplexMode
and FullDuplexMode
type parameters have been removed from SPI master and slave
drivers. It is now possible to execute half-duplex and full-duplex operations on the same SPI bus.
Driver construction
- The
Spi::new_half_duplex
constructor has been removed. Usenew
(ornew_typed
) instead. - The
with_pins
methods have been removed. Use the individualwith_*
functions instead. - The
with_mosi
andwith_miso
functions now take input-output peripheral signals to support half-duplex mode.
- let mut spi = Spi::new_half_duplex(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
- .with_pins(sck, mosi, miso, sio2, sio3, cs);
+ let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0)
+ .with_sck(sck)
+ .with_cs(cs)
+ .with_mosi(mosi)
+ .with_miso(miso)
+ .with_sio2(sio2)
+ .with_sio3(sio3);
Transfer functions
The Spi<'_, SPI, HalfDuplexMode>::read
and Spi<'_, SPI, HalfDuplexMode>::write
functions have been replaced by
half_duplex_read
and half_duplex_write
.
let mut data = [0u8; 2];
let transfer = spi
- .read(
+ .half_duplex_read(
SpiDataMode::Single,
Command::Command8(0x90, SpiDataMode::Single),
Address::Address24(0x000000, SpiDataMode::Single),
0,
&mut data,
)
.unwrap();
let transfer = spi
- .write(
+ .half_duplex_write(
SpiDataMode::Quad,
Command::Command8(write as u16, command_data_mode),
Address::Address24(
write as u32 | (write as u32) << 8 | (write as u32) << 16,
SpiDataMode::Quad,
),
0,
dma_tx_buf,
)
.unwrap();
Slave-mode SPI
Driver construction
The constructors no longer accept pins. Use the with_pin_name
setters instead.
let mut spi = Spi::new(
peripherals.SPI2,
- sclk,
- mosi,
- miso,
- cs,
SpiMode::Mode0,
-);
+)
+.with_sclk(sclk)
+.with_mosi(mosi)
+.with_miso(miso)
+.with_cs(cs);
UART event listening
The following functions have been removed:
listen_at_cmd
unlisten_at_cmd
listen_tx_done
unlisten_tx_done
listen_rx_fifo_full
unlisten_rx_fifo_full
at_cmd_interrupt_set
tx_done_interrupt_set
rx_fifo_full_interrupt_set
reset_at_cmd_interrupt
reset_tx_done_interrupt
reset_rx_fifo_full_interrupt
You can now use the UartInterrupt
enum and the corresponding listen
, unlisten
, interrupts
and clear_interrupts
functions.
Use interrupts
in place of <INTERRUPT>_interrupt_set
and clear_interrupts
in place of the old reset_
functions.
UartInterrupt
:
AtCmd
TxDone
RxFifoFull
Checking interrupt bits is now done using APIs provided by enumset. For example, to see if
a particular interrupt bit is set, use contains
:
-serial.at_cmd_interrupt_set()
+serial.interupts().contains(UartInterrupt::AtCmd)
You can now listen/unlisten multiple interrupt bits at once:
-uart0.listen_at_cmd();
-uart0.listen_rx_fifo_full();
+uart0.listen(UartInterrupt::AtCmd | UartConterrupt::RxFifoFull);
I2S changes
The I2S driver has been moved to i2s::master
-use esp_hal::i2s::{DataFormat, I2s, Standard};
+use esp_hal::i2s::master::{DataFormat, I2s, Standard};
Removed i2s
traits
The following traits have been removed:
I2sWrite
I2sWriteDma
I2sRead
I2sReadDma
I2sWriteDmaAsync
I2sReadDmaAsync
You no longer have to import these to access their respective APIs. If you used these traits
in your functions as generic parameters, you can use the I2s
type directly instead.
For example:
-fn foo(i2s: &mut impl I2sWrite) {
+fn foo(i2s: &mut I2s<'_, I2S0, Blocking>) {
// ...
}
DMA related changes
Circular DMA transfer's available
returns Result<usize, DmaError>
now
In case of any error you should drop the transfer and restart it.
loop {
- let avail = transfer.available();
+ let avail = match transfer.available() {
+ Ok(avail) => avail,
+ Err(_) => {
+ core::mem::drop(transfer);
+ transfer = i2s_tx.write_dma_circular(&tx_buffer).unwrap();
+ continue;
+ },
+ };
Channel, ChannelRx and ChannelTx types have changed
Channel
'sAsync
/Blocking
mode has been moved before the channel instance parameter.ChannelRx
andChannelTx
have gained a newAsync
/Blocking
mode parameter.
-Channel<'d, DmaChannel0, Async>
+Channel<'d, Async, DmaChannel0>
-ChannelRx<'d, DmaChannel0>
+ChannelRx<'d, Async, DmaChannel0>
-ChannelTx<'d, DmaChannel0>
+ChannelTx<'d, Async, DmaChannel0>
Removed peripheral_input
and into_peripheral_output
from GPIO pin types
Creating peripheral interconnect signals now consume the GPIO pin used for the connection.
The previous signal function have been replaced by split
. This change affects the following APIs:
GpioPin
AnyPin
-let input_signal = gpioN.peripheral_input();
-let output_signal = gpioN.into_peripheral_output();
+let (input_signal, output_signal) = gpioN.split();
into_peripheral_output
, split
(for output pins only) and peripheral_input
have been added to
the GPIO drivers (Input
, Output
, OutputOpenDrain
and Flex
) instead.
ETM changes
- The types are no longer prefixed with
GpioEtm
,TimerEtm
orSysTimerEtm
. You can still use
import aliasses in case you ...
0.21.1
0.21.0
Please note that only changes to the esp-hal
package are tracked in these release notes.
Migration Guides
esp-hal
: https://github.com/esp-rs/esp-hal/blob/v0.21.0/esp-hal/MIGRATING-0.20.mdesp-hal-embassy
: https://github.com/esp-rs/esp-hal/blob/v0.21.0/esp-hal-embassy/MIGRATING-0.3.mdesp-wifi
: https://github.com/esp-rs/esp-hal/blob/v0.21.0/esp-wifi/MIGRATING-0.9.md
Changelog
Added
- Introduce traits for the DMA buffer objects (#1976, #2213)
- Implement
embedded-hal
output pin traits forNoPin
(#2019, #2133) - Added
esp_hal::init
to simplify HAL initialisation (#1970, #1999) - Added GpioPin::degrade to create ErasePins easily. Same for AnyPin by accident. (#2075)
- Added missing functions to
Flex
:unlisten
,is_interrupt_set
,wakeup_enable
,wait_for_high
,wait_for_low
,wait_for_rising_edge
,wait_for_falling_edge
,wait_for_any_edge
. (#2075) Flex
now implementsWait
. (#2075)- Added sleep and wakeup support for esp32c2 (#1922)
Input
,Output
,OutputOpenDrain
andFlex
now implementPeripheral
. (#2094)- Previously unavailable memory is available via
.dram2_uninit
section (#2079) - You can now use
Input
,Output
,OutputOpenDrain
andFlex
pins as EXTI and RTCIO wakeup sources (#2095) - Added
Rtc::set_current_time
to allow setting RTC time, andRtc::current_time
to getting RTC time while taking into account boot time (#1883) - Added APIs to allow connecting signals through the GPIO matrix. (#2128)
- Allow I8080 transfers to be cancelled on the spot (#2191)
- Implement
TryFrom<u32>
forledc::timer::config::Duty
(#1984) - Expose
RtcClock::get_xtal_freq
andRtcClock::get_slow_freq
publically for all chips (#2183) - TWAI support for ESP32-H2 (#2199)
- Make
DmaDescriptor
methods public (#2237) - Added a way to configure watchdogs in
esp_hal::init
(#2180) - Introduce
DmaRxStreamBuf
(#2242) - Implement
embedded_hal_async::delay::DelayNs
forTIMGx
timers (#2084) - Added
Efuse::read_bit
(#2259) - Limited SPI slave support for ESP32 (Modes 1 and 3 only) (#2278)
- Added
Rtc::disable_rom_message_printing
(S3 and H2 only) (#2280) - Added
esp_hal::time::{Duration, Instant}
(#2304)
Changed
- Bump MSRV to 1.79.0 (#1971)
- Make saving and restoring SHA digest state an explicit operation (#2049)
- Reordered RX-TX pairs in all APIs to be consistent (#2074)
- Make saving and restoring SHA digest state an explicit operation (#2049)
Delay::new()
is now aconst
function (#1999)Input
,Output
,OutputOpenDrain
andFlex
are now type-erased by default. Use the newnew_typed
constructor to keep using the ZST pin types. (#2075)- To avoid confusion with the
Rtc::current_time
wall clock time APIs, we've renamedesp_hal::time::current_time
toesp_hal::time::now
. (#2091) - Renamed
touch::Continous
totouch::Continuous
. (#2094) - Faster SHA (#2112)
- The (previously undocumented)
ErasedPin
enum has been replaced with theErasedPin
struct. (#2094) - Renamed and merged
Rtc::get_time_us
andRtc::get_time_ms
intoRtc::time_since_boot
(#1883) - ESP32: Added support for touch sensing on GPIO32 and 33 (#2109)
- Removed gpio pin generics from I8080 driver type. (#2171)
- I8080 driver now decides bus width at transfer time rather than construction time. (#2171)
- Migrate the I8080 driver to a move based API (#2191)
- Replaced
AnyPin
withInputSignal
andOutputSignal
and renamedErasedPin
toAnyPin
(#2128) - Replaced the
ErasedTimer
enum with theAnyTimer
struct. (#2144) Camera
andAesDma
now support erasing the DMA channel type (#2258)- Changed the parameters of
Spi::with_pins
to no longer be optional (#2133) - Renamed
DummyPin
toNoPin
and removed all internal logic from it. (#2133) - The
NO_PIN
constant has been removed. (#2133) - Allow handling interrupts while trying to lock critical section on multi-core chips. (#2197)
- Migrate
Camera
to a move based API (#2242). - Removed the PS-RAM related features, replaced by
quad-psram
/octal-psram
,init_psram
takes a configuration parameter, it's now possible to auto-detect PS-RAM size (#2178) EspTwaiFrame
constructors now accept any type that converts intoesp_hal::twai::Id
(#2207)- Change
DmaTxBuf
to support PSRAM onesp32s3
(#2161) - I2c
transaction
is now also available as a inherent function, lift size limit onwrite
,read
andwrite_read
(#2262) - SPI transactions are now cancelled if the transfer object (or async Future) is dropped. (#2216)
- The DMA channel types have been removed from peripherals (#2261)
I2C
driver renamed toI2c
(#2320)
Fixed
- SHA driver can now be safely used in multiple contexts concurrently (#2049)
- Fixed an issue with DMA transfers potentially not waking up the correct async task (#2065)
- Fixed an issue with LCD_CAM i8080 where it would send double the clocks in 16bit mode (#2085)
- Fix i2c embedded-hal transaction (#2028)
- Fix some inconsistencies in DMA interrupt bits (#2169)
- Fix SPI DMA alternating
write
andread
for ESP32 and ESP32-S2 (#2131) - Fix I2C ending up in a state when only re-creating the peripheral makes it useable again (#2141)
- Fix
SpiBus::transfer
transferring data twice in some cases (#2159) - Fixed UART freezing when using
RcFast
clock source on ESP32-C2/C3 (#2170) - I2S: on ESP32 and ESP32-S2 data is now output to the right (WS=1) channel first. (#2194)
- SPI: Fixed an issue where unexpected data was written outside of the read buffer (#2179)
- SPI: Fixed an issue where
wait
has returned before the DMA has finished writing the memory (#2179) - SPI: Fixed an issue where repeated calls to
dma_transfer
may end up looping indefinitely (#2179) - SPI: Fixed an issue that prevented correctly reading the first byte in a transaction (#2179)
- SPI: ESP32: Send address with correct data mode even when no data is sent. (#2231)
- SPI: ESP32: Allow using QSPI mode on SPI3. (#2245)
- PARL_IO: Fixed an issue that caused garbage to be output at the start of some requests (#2211)
- TWAI on ESP32 (#2207)
- TWAI should no longer panic when receiving a non-compliant frame (#2255)
- OneShotTimer: fixed
delay_nanos
behaviour (#2256) - Fixed unsoundness around
Efuse
(#2259)
Removed
- Removed
digest::Digest
implementation from SHA (#2049) - Removed
NoPinType
in favour ofDummyPin
. (#2068) - Removed the
async
,embedded-hal-02
,embedded-hal
,embedded-io
,embedded-io-async
, andufmt
features (#2070) - Removed the
GpioN
type aliasses. UseGpioPin<N>
instead. (#2073) - Removed
Peripherals::take
. Useesp_hal::init
to obtainPeripherals
(#1999) - Removed
AnyInputOnlyPin
in favour ofAnyPin
. (#2071) - Removed the following functions from
GpioPin
:is_high
,is_low
,set_high
,set_low
,set_state
,is_set_high
,is_set_low
,toggle
. (#2094) - Removed
Rtc::get_time_raw
(#1883) - Removed
_with_default_pins
UART constructors (#2132) - Removed transfer methods
send
,send_dma
andsend_dma_async
fromI8080
(#2191) - Removed
uart::{DefaultRxPin, DefaultTxPin}
(#2132) - Removed
PcntSource
andPcntInputConfig
. (#2134) - Removed the
place-spi-driver-in-ram
feature, this is now enabled via esp-config (#2156) - Removed
esp_hal::spi::slave::prelude
(#2260) - Removed
esp_hal::spi::slave::WithDmaSpiN
traits (#2260) - The
WithDmaAes
trait has been removed (#2261) - The
I2s::new_i2s1
constructor has been removed (#2261)
v0.20.1
0.20.0
Please note that only changes to the esp-hal
package are tracked in these release notes.
Migration Guide
Peripheral driver constructors don't take InterruptHandlers anymore
Some peripherals used to take the interrupt handler via constructor. We have now unified this behaviour so that all peripherals use the same set_interrupt_handler
method. We also have a new trait to abstract over this, InterruptConfigurable
.
- Peripheral::new(/* params */, handler)
+ peripheral.set_interrupt_handler(handler);
OneShotTimer
and PeriodicTimer
structs now use PeripheralRef
This was something we missed on the initial impl. The migration is quite simple, there is a new lifetime parameter to contend with.
- OneShotTimer<ErasedTimer>;
+ OneShotTimer<'static, ErasedTimer>;
DMA buffer changes and SpiDma
changes
To allow efficient queuing of DMA requests, we've changed how the DMA is interacted with. #1856 introduces new wrapper types DmaTxBuf
, DmaRxBuf
and DmaTxRxBuf
. These are currently light wrappers around slices and descriptors, but allows us to do more complex checks for future devices and peripherals. Thanks to these changes, we have been able to remove the FlashSafeDma
wrapper too.
let (tx_buffer, tx_descriptors, rx_buffer, rx_descriptors) = dma_buffers!(32000);
+ let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
+ let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
We've also decoupled the DMA buffers and descriptors from the SpiDma
struct itself, this means the end user can manage the queuing of DMA requests for more efficient operation. If you don't wish to manage this yourself and want to use the embedded_hal::spi::*
traits, it's simple enough to opt back into the HAL buffer management like so.
let mut spi = Spi::new(peripherals.SPI2, 100.kHz(), SpiMode::Mode0, &clocks)
.with_pins(Some(sclk), Some(mosi), Some(miso), Some(cs))
.with_dma(dma_channel.configure_for_async(false, DmaPriority::Priority0))
+ .with_buffers(dma_tx_buf, dma_rx_buf);
We also added inherent methods onto SpiDmaBus
, which due to the way type inference works may introduce breaking changes if you were using the async API. You may need to fully qualify the trait method or call the new inherent _async
methods.
- spi.transfer_in_place(&mut buf).await?;
+ spi.transfer_in_place_async(&mut buf).await?;
SystemTimer
changes
- The type signature of both
SysTimer
andAlarm
has been changed to allow for creation of alarms in eitherBlocking
orAsync
separately. We have provided a convenience method to create all alarms in the same mode, just as it behaved before this release.
- let syst = SystemTimer::new_async(peripherals.SYSTIMER);
+ let syst = SystemTimer::new(peripherals.SYSTIMER);
+ let alarms = syst.split_async::<esp_hal::timer::systimer::Target>()
SystemTimer::TICKS_PER_SECOND
has been replaced bySystemTimer::ticks_per_second()
.
Sha
state is now stored outside the Sha
peripheral
The state is now stored separately to allow multiple Sha
operations concurrently.
- sha.update(remaining).unwrap();
+ let mut sha1 = Sha1::new();
+ Sha::update(&mut sha1, remaining).unwrap();
Remove fn free(self)
from HMAC
The fn free(self)
method is no longer available, in favour of the PeripheralRef
API.
RSA modular multiplication
RsaModularMultiplication
has been consolidated for all targets.
ESP32 changes
let r = compute_r(&BIGNUM_3);
let mut mod_multi =
RsaModularMultiplication::<Op512, Blocking>::new(
&mut ctx.rsa,
+ BIGNUM_1.as_words(), // Operand A
BIGNUM_3.as_words(), // Modulus
+ r.as_words(),
compute_mprime(&BIGNUM_3),
);
-mod_multi.start_step1(BIGNUM_1.as_words(), r.as_words()); // Operand A
-mod_multi.start_step2(BIGNUM_2.as_words()); // Operand B
+mod_multi.start_modular_multiplication(BIGNUM_2.as_words()); // Operand B
mod_multi.read_results(&mut outbuf);
Non-ESP32 changes
let r = compute_r(&BIGNUM_3);
let mut mod_multi =
RsaModularMultiplication::<operand_sizes::Op512, esp_hal::Blocking>::new(
&mut ctx.rsa,
BIGNUM_1.as_words(), // Operand A
- BIGNUM_2.as_words(), // Operand B
BIGNUM_3.as_words(), // Modulus
+ r.as_words(),
compute_mprime(&BIGNUM_3),
);
-mod_multi.start_modular_multiplication(r.as_words());
+mod_multi.start_modular_multiplication(BIGNUM_2.as_words()); // Operand B
mod_multi.read_results(&mut outbuf);
Simpler way to initialise embassy and esp-wifi
You no longer have to spell out a bunch of type conversions, to initialize esp-wifi or embassy with a single timer. We provide conversions for TimerGroup
times as well as SysTimer
alarms.
Note that if you need to pass multiple timers to embassy, you will still need to do the conversions yourself.
AnyPin
, AnyInputOnyPin
and DummyPin
are now accessible from gpio
directly
- use esp_hal::gpio::any_pin::AnyPin;
- - use esp_hal::gpio::dummy_pin::DummyPin;
+ use esp_hal::gpio::AnyPin;
+ use esp_hal::gpio::DummyPin;
Initialising embassy
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
-let timer0: ErasedTimer = timg0.timer0.into();
-let timers = [OneShotTimer::new(timer0)];
-let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
-esp_hal_embassy::init(&clocks, timers);
+esp_hal_embassy::init(&clocks, timg0.timer0);
let systimer = SystemTimer::new(peripherals.SYSTIMER).split::<Target>();
-let alarm0: ErasedTimer = systimer.alarm0.into();
-let timers = [OneShotTimer::new(alarm0)];
-let timers = mk_static!([OneShotTimer<ErasedTimer>; 1], timers);
-esp_hal_embassy::init(&clocks, timers);
+esp_hal_embassy::init(&clocks, systimer.alarm0);
Initializing esp-wifi
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
-let timer0: ErasedTimer = timg0.timer0.into();
-let timer = PeriodicTimer::new(timer0);
let init = initialize(
EspWifiInitFor::Wifi,
- timer,
+ timg0.timer0,
Rng::new(peripherals.RNG),
peripherals.RADIO_CLK,
clocks,
)
.unwrap();
let systimer = esp_hal::timer::systimer::SystemTimer::new(peripherals.SYSTIMER).split::<esp_hal::timer::systimer::Target>();
-let alarm0: ErasedTimer = systimer.alarm0.into();
-let alarm = PeriodicTimer::new(alarm0);
let init = initialize(
EspWifiInitFor::Wifi,
- alarm,
+ systimer.alarm0,
Rng::new(peripherals.RNG),
peripherals.RADIO_CLK,
clocks,
)
.unwrap();
Floating point support
Floating point operations in interrupt contexts are no longer allowed by default. If you experience Cp0Disabled
panics, you should try enabling the float-save-restore
feature on xtensa-lx-rt
.
Changelog
Added
- Introduce DMA buffer objects (#1856, #1985)
- Added new
Io::new_no_bind_interrupt
constructor (#1861) - Added touch pad support for esp32 (#1873, #1956)
- Allow configuration of period updating method for MCPWM timers (#1898)
- Add self-testing mode for TWAI peripheral. (#1929)
- Added a
PeripheralClockControl::reset
to the driver constructors where missing (#1893) - Added
digest::Digest
implementation to SHA (#1908) - Added
debugger::debugger_connected
. (#1961) - DMA: don't require
Sealed
to implementReadBuffer
andWriteBuffer
(#1921) - Allow DMA to/from psram for esp32s3 (#1827)
- Added missing methods to
SpiDmaBus
(#2016). - PARL_IO use ReadBuffer and WriteBuffer for Async DMA (#1996)
Changed
- Peripheral driver constructors don't take
InterruptHandler
s anymore. Useset_interrupt_handler
to explicitly set the interrupt handler now. (#1819) - Migrate SPI driver to use DMA buffer objects (#1856, #1985)
- Use the peripheral ref pattern for
OneShotTimer
andPeriodicTimer
(#1855) - Improve SYSTIMER API (#1871)
- SHA driver now use specific structs for the hashing algorithm instead of a parameter. (#1908)
- Remove
fn free(self)
in HMAC which goes against esp-hal API guidelines (#1972) AnyPin
,AnyInputOnyPin
andDummyPin
are now accessible fromgpio
module (#1918)- Changed the RSA modular multiplication API to be consistent across devices (#2002)
Fixed
- Improve error detection in the I2C driver (#1847)
- Fix I2S async-tx (#1833)
- Fix PARL_IO async-rx (#1851)
- SPI: Clear DMA interrupts before (not after) DMA starts (#1859)
- SPI: disable and re-enable MISO and MOSI in
start_transfer_dma
,start_read_bytes_dma
andstart_write_bytes_dma
accordingly (#1894) - TWAI: GPIO pins are not configured as input and output (#1906)
- ESP32C6: Make ADC usable after TRNG deinicialization (#1945)
- We should no longer generate 1GB .elf files for ESP32C2 and ESP32C3 (#1962)
- Reset peripherals in driver constructors where missing (#1893, #1961)
- Fixed ESP32-S2 systimer interrupts (#1979)
- Software interrupt 3 is no longer available when it is required by
esp-hal-embassy
. (#2011) - ESP32: Fixed async RSA (#2002)
Removed
0.19.0
Please note that only changes to the esp-hal
package are tracked in these release notes.
Migration Guide
Coming Soon™️ (sorry, I forgot to write it 😅)
Changelog
Added
- uart: Added
with_cts
/with_rts
s methods to configure CTS, and RTS pins (#1592) - uart: Constructors now require TX and RX pins (#1592)
- uart: Added
Uart::new_with_default_pins
constructor (#1592) - uart: Added
UartTx
andUartRx
constructors (#1592) - Add Flex / AnyFlex GPIO pin driver (#1659)
- Add new
DmaError::UnsupportedMemoryRegion
- used memory regions are checked when preparing a transfer now (#1670) - Add DmaTransactionTxOwned, DmaTransactionRxOwned, DmaTransactionTxRxOwned, functions to do owning transfers added to SPI half-duplex (#1672)
- uart: Implement
embedded_io::ReadReady
forUart
andUartRx
(#1702) - ESP32-S3: Expose optional HSYNC input in LCD_CAM (#1707)
- ESP32-C6: Support lp-core as wake-up source (#1723)
- Add support for GPIO wake-up source (#1724)
- gpio: add DummyPin (#1769)
- dma: add Mem2Mem to support memory to memory transfer (#1738)
- Add
uart
wake source (#1727) #[ram(persistent)]
option to replace the unsounduninitialized
option (#1677)- uart: Make
rx_timeout
optional in Config struct (#1759) - Add interrupt related functions to
PeriodicTimer
/OneShotTimer
, addedErasedTimer
(#1753) - Added blocking
read_bytes
method toUart
andUartRx
(#1784)
Fixed
- ESP32-S3: Fix DMA waiting check in LCD_CAM (#1707)
- TIMG: Fix interrupt handler setup (#1714)
- Fix
sleep_light
for ESP32-C6 (#1720) - ROM Functions: Fix address of
ets_update_cpu_frequency_rom
(#1722) - Fix
regi2c_*
functions foresp32h2
(#1737) - Improved
#[ram(zeroed)]
soundness by adding abytemuck::Zeroable
type bound (#1677) - EESP32-S2 / ESP32-S3: Fix UsbDm and UsbDp for Gpio19 and Gpio20
- Fix reading/writing small buffers via SPI master async dma (#1760)
- Remove unnecessary delay in rtc_ctnl (#1794)
Changed
- Refactor
Dac1
/Dac2
drivers into a singleDac
driver (#1661) - esp-hal-embassy: make executor code optional (but default) again
- Improved interrupt latency on RISC-V based chips (#1679)
esp_wifi::initialize
no longer requires running maximum CPU clock, instead check it runs above 80MHz. (#1688)- Move DMA descriptors from DMA Channel to each individual peripheral driver. (#1719)
- Support DMA chunk sizes other than the default 4092 (#1758)
- Improved interrupt latency on Xtensa based chips (#1735)
- Improve PCNT api (#1765)
Removed
0.18.0
Please note that only changes to the esp-hal
package are tracked in these release notes.
Migration Guide
SystemControl
We have removed the SystemExt
trait, meaning that the SYSTEM
peripheral no longer has a split()
method. Instead, we now instantiate a new SystemControl
struct:
use esp_hal::{peripherals::Peripherals, system::SystemControl, clock::ClockControl};
let peripherals = Peripherals::take();
let system = SystemControl::new(peripherals.SYSTEM);
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
Timers
There have been a number of changes to the various timer drivers in esp-hal
, notable the reorganization of their modules. While previously we had systimer
(SYSTIMER
) and timer
(TIMGx
) modules, these have been combined into a common module, and are now available at timer::systimer
and timer::timg0
respectively.
Additionally, there have been some minor changes in API relating to the introduction of the timer::Timer
trait; these should be mostly straight forward to resolve, refer to the documentation.
GPIO
The GPIO system has been reworked to remove into_X
methods, in favour of a concrete pin type.
Old into_X method | New type |
---|---|
output | Output |
output open drain | OutputOpenDrain |
input | Input |
For example code such as io.pins.gpio18.into_push_pull_output()
should be replaced with Output::new(io.pins.gpio18)
for each respective case. To see more discussion and examples for this change, see the RFC and implementation PR.
esp-hal-embassy
As of this release, support for [Embassy] has been extracted from esp-hal
into its own package, esp-hal-embassy
. This is nearly a drop-in replacement, only a few small changes are required.
First, add the new dependency to your Cargo.toml
:
[dependencies]
esp-hal-embassy = { version = "0.1.0", features = [
"time-timg0", # Compatible with all chips
# "time-systimer-16mhz", # Compatible with all chips except ESP32 and ESP32-S2
# "time-systimer-80mhz", # Compatible with ESP32-S2 only
] }
Note that in previous version, the time-systimer-*
features were incorrectly named time-systick-*
; this has now been rectified. Additionally, as of this release it is no longer required to select an executor via its Cargo feature; both the thread-mode and interrupt-mode executors are now available by default.
Next, simply replace any references to the esp_hal::embassy
module and its children with the esp_hal_embassy
package instead. This can likely be accomplished with a simple search-and-replace in your text editor.
Changelog
Added
- i2c: implement
I2C:transaction
forembedded-hal
andembedded-hal-async
(#1505) - spi: implement
with_bit_order
(#1537) - ESP32-PICO-V3-02: Initial support (#1155)
time::current_time
API (#1503)- ESP32-S3: Add LCD_CAM Camera driver (#1483)
embassy-usb
support (#1517)- SPI Slave support for ESP32-S2 (#1562)
- Add new generic
OneShotTimer
andPeriodicTimer
drivers, plus newTimer
trait which is implemented forTIMGx
andSYSTIMER
(#1570)
Fixed
- i2c: i2c1_handler used I2C0 register block by mistake (#1487)
- Removed ESP32 specific code for resolutions > 16 bit in ledc embedded_hal::pwm max_duty_cycle function. (#1441)
- Fixed division by zero in ledc embedded_hal::pwm set_duty_cycle function and converted to set_duty_hw instead of set_duty to eliminate loss of granularity. (#1441)
- Embassy examples now build on stable (#1485)
- Fix delay on esp32h2 (#1535)
- spi: fix dma wrong mode when using eh1 blocking api (#1541)
- uart: make
uart::UartRx::read_byte
public (#1547) - Fix async serial-usb-jtag (#1561)
- Feeding
RWDT
now actually works (#1645)
Changed
- Removed unneeded generic parameters on
Usb
(#1469) - Created virtual peripherals for CPU control and radio clocks, rather than splitting them from
SYSTEM
(#1428) IO
,ADC
,DAC
,RTC*
,LEDC
,PWM
andPCNT
drivers have been converted to camel case format (#1473)- RNG is no longer TRNG, the
CryptoRng
implementation has been removed. To track this being re-added see #1499 (#1498) - Make software interrupts shareable (#1500)
- The
SystemParts
struct has been renamed toSystemControl
, and now has a constructor which takes theSYSTEM
peripheral (#1495) - Timer abstraction: refactor
systimer
andtimer
modules into a commontimer
module (#1527) - Removed the
embassy-executor-thread
andembassy-executor-interrupt
features, they are now enabled by default whenembassy
is enabled. (#1485) - Software interrupt 3 is now used instead of software interrupt 0 on the thread aware executor on multicore systems (#1485)
- Timer abstraction: refactor
systimer
andtimer
modules into a commontimer
module (#1527) - Refactoring of GPIO module, have drivers for Input,Output,OutputOpenDrain, all drivers setup their GPIOs correctly (#1542)
- DMA transactions are now found in the
dma
module (#1550) - Remove unnecessary generics from PARL_IO driver (#1545)
- Use
Level enum
in GPIO constructors instead of plain bools (#1574) - rmt: make ChannelCreator public (#1597)
Removed
0.17.0
Please note that only changes to the esp-hal package are tracked in these release notes. Read the full changelog entry for all the changes.
[email protected]
Migration Guide
This release changes interrupt handler binding from link-time binding to runtime-binding. This increases flexibility of how interrupts can be used, but the main reason is two allow mixing mixing async and non-async drivers in the same application.
Key changes
The biggest change is the removal of the #[interrupt]
macro. It has been replaced by the #[handler]
macro which works differently slightly differently.
Now you have to bind the interrupt handler explicitly. The supported peripheral drivers either take a new optional parameter to their constructor or it will offer a set_interrupt_handler
function. Don't worry, if you forget to do this, the compiler will emit an unused warning for the #[handler]
function.
The second change is that most drivers will now have a MODE
parameter with some new constructors to initialize a driver in Blocking
or Async
mode. You will need to account for this in your code.
Finally, most root level re-exports are now gone, instead, you should import from the specific module.
Below is a list of key changes you need to make to upgrade.
There is no longer a need to enable interrupts manually unless you are changing a priority later in the application. This change also means the interrupt is enabled once the interrupt is used, so please ensure that you have the proper ordering of initialization or critical sections to account for that.
- interrupt::enable(Interrupt::GPIO, Priority::Priority2).unwrap();
Use the new handler macro.
- #[interrupt]
+ #[handler]
Ensure you set the handler, depending on the peripheral this may be part of the constructor or a method such as the one below.
+ io.set_interrupt_handler(handler);
Interrupts are now tightly coupled to their priority, meaning you can pass a priority to the handler macro. The default unless specified is the lowest priority.
+ #[handler(priority = "Priority::max()")]
0.16.1
0.16.0
Please note that only changes to the esp-hal
package are tracked in these release notes.
[email protected]
Migration Guide
This release consolidates the various chip-specific HAL packages into a single package, esp-hal
. Projects which previously depended on the chip-specific packages (esp32-hal
, esp32c3-hal
, etc.) should be updated to use esp-hal
instead.
We now have self-hosted documentation built for each supported chip! See https://docs.esp-rs.org/esp-hal/ for more details.
In order to migrate your project to the latest release, please follow the short guide below.
If you encounter any issues during the migration process, please open an issue, and we will do our best to resolve them as expediently as possible.
Migrating to esp-hal
In general, only two steps should be required for this migration:
- Update your dependencies in the Cargo manifest
- Update any references to the HAL in your project's source files
Depending on which features you are using, there may be some additional changes required. Please refer to the esp-hal
documentation for a full list of features.
Updating Dependencies
First, update your dependencies in Cargo.toml
and enable the appropriate feature for the chip being targeted.
For example, if your project previously depended on esp32c3-hal
then open your project's Cargo.toml
file and make the following change:
- esp32c3-hal = "0.15.0"
+ esp-hal = { version = "0.16.0", features = ["esp32c3"] }
Update Imports
Next, update any references to the chip-specific HAL package (e.g. esp32c3-hal
) in your project's source files. This can likely be done with a global search-and-replace in your favourite text editor.
In general this will only affect imports, e.g.:
- use esp32c3_hal::*;
+ use esp_hal::*;
Changelog
Added
- Add initial support for the ESP32-P4 (#1101)
- Implement
embedded_hal::pwm::SetDutyCycle
trait forledc::channel::Channel
(#1097) - ESP32-P4: Add initial GPIO support (#1109)
- ESP32-P4: Add initial support for interrupts (#1112)
- ESP32-P4: Add efuse reading support (#1114)
- ESP32-S3: Added LCD_CAM I8080 driver (#1086)
- Allow for splitting of the USB Serial JTAG peripheral into tx/rx components (#1024)
RngCore
trait is implemented (#1122)- Support Rust's
stack-protector
feature (#1135) - Adding clock support for
ESP32-P4
(#1145) - Implementation OutputPin and InputPin for AnyPin (#1067)
- Implement
estimate_xtal_frequency
for ESP32-C6 / ESP32-H2 (#1174) - A way to push into I2S DMA buffer via a closure (#1189)
- Added basic
LP-I2C
driver for C6 (#1185) - Ensuring that the random number generator is TRNG. (#1200)
- ESP32-C6: Add timer wakeup source for deepsleep (#1201)
- Introduce
InterruptExecutor::spawner()
(#1211)
Fixed
- Fix embassy-time tick rate not set when using systick as the embassy timebase (#1124)
- Fix
get_raw_core
on Xtensa (#1126) - Fix docs.rs documentation builds (#1129)
- Fix circular DMA (#1144)
- Fix
hello_rgb
example for ESP32 (#1173) - Fixed the multicore critical section on Xtensa (#1175)
- Fix timer
now
for esp32c3 and esp32c6 (#1178) - Wait for registers to get synced before reading the timer count for all chips (#1183)
- Fix I2C error handling (#1184)
- Fix circular DMA (#1189)
- Fix esp32c3 uart initialization (#1156)
- Fix ESP32-S2 I2C read (#1214)
- Reset/init UART if it's not the console UART (#1213)
Changed
- DmaDescriptor struct to better model the hardware (#1054)
- DMA descriptor count no longer needs to be multiplied by 3 (#1054)
- RMT channels no longer take the channel number as a generic param (#959)
- The
esp-hal-common
package is now calledesp-hal
(#1131) - Refactor the
Trace
driver to be generic around its peripheral (#1140) - Auto detect crystal frequency based on
RtcClock::estimate_xtal_frequency()
(#1165) - ESP32-S3: Configure 32k ICACHE (#1169)
- Lift the minimal buffer size requirement for I2S (#1189)
Removed
- Remove
xtal-26mhz
andxtal-40mhz
features (#1165) - All chip-specific HAL packages have been removed (#1196)
Breaking
ADC
andDAC
drivers now take virtual peripherals in their constructors, instead of splittingAPB_SARADC
/SENS
(#1100)- The
DAC
driver's constructor is nownew
instead ofdac
, to be more consistent with other APIs (#1100) - The DMA peripheral is now called
Dma
for devices with both PDMA and GDMA controllers (#1125) - The
ADC
driver's constructor is nownew
instead ofadc
, to be more consistent with other APIs (#1133) embassy-executor
'sintegrated-timers
is no longer enabled by default.- Renamed
embassy-time-systick
toembassy-time-systick-16mhz
for use with all chips with a systimer, exceptesp32s2
. Addedembassy-time-systick-80mhz
specifically for theesp32s2
. (#1247)