Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework i2c #2437

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- GPIO ETM tasks and events now accept `InputSignal` and `OutputSignal` (#2427)
- `spi::master::Config` and `{Spi, SpiDma, SpiDmaBus}::apply_config` (#2448)
- `embassy_embedded_hal::SetConfig` is now implemented for `{Spi, SpiDma, SpiDmaBus}` (#2448)
- `I2c::{apply_config(), with_sda(), with_scl()}` (#2437)
- `I2c` now implements `embassy_embedded_hal::SetConfig` (#2437)

### Changed

Expand All @@ -54,6 +56,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- UART configuration types have been moved to `esp_hal::uart` (#2449)
- `spi::master::Spi::new()` no longer takes `frequency` and `mode` as a parameter. (#2448)
- Peripheral interconnections via GPIO pins now use the GPIO matrix. (#2419)
- The `I2c` master driver has been moved to `esp_hal::i2c::master`. (#2437)
- `I2c` SCL timeout is now defined in bus clock cycles. (#2437)

### Fixed

Expand Down Expand Up @@ -90,6 +94,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `GpioEtmEventRising`, `GpioEtmEventFalling`, `GpioEtmEventAny` types have been replaced with `Event` (#2427)
- The `TaskSet`, `TaskClear`, `TaskToggle` types have been replaced with `Task` (#2427)
- `{Spi, SpiDma, SpiDmaBus}` configuration methods (#2448)
- `I2c::new()` no longer takes `frequency` and pins as parameters. (#2437)

## [0.21.1]

Expand Down
14 changes: 7 additions & 7 deletions esp-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ xtensa-lx = { version = "0.9.0", optional = true }
# IMPORTANT:
# Each supported device MUST have its PAC included below along with a
# corresponding feature.
esp32 = { version = "0.33.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "390c88b", features = ["critical-section", "rt"], optional = true }
esp32c2 = { version = "0.22.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "390c88b", features = ["critical-section", "rt"], optional = true }
esp32c3 = { version = "0.25.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "390c88b", features = ["critical-section", "rt"], optional = true }
esp32c6 = { version = "0.16.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "390c88b", features = ["critical-section", "rt"], optional = true }
esp32h2 = { version = "0.12.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "390c88b", features = ["critical-section", "rt"], optional = true }
esp32s2 = { version = "0.24.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "390c88b", features = ["critical-section", "rt"], optional = true }
esp32s3 = { version = "0.28.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "390c88b", features = ["critical-section", "rt"], optional = true }
esp32 = { version = "0.33.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "58e9556", features = ["critical-section", "rt"], optional = true }
esp32c2 = { version = "0.22.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "58e9556", features = ["critical-section", "rt"], optional = true }
esp32c3 = { version = "0.25.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "58e9556", features = ["critical-section", "rt"], optional = true }
esp32c6 = { version = "0.16.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "58e9556", features = ["critical-section", "rt"], optional = true }
esp32h2 = { version = "0.12.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "58e9556", features = ["critical-section", "rt"], optional = true }
esp32s2 = { version = "0.24.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "58e9556", features = ["critical-section", "rt"], optional = true }
esp32s3 = { version = "0.28.0", git = "https://github.com/esp-rs/esp-pacs.git", rev = "58e9556", features = ["critical-section", "rt"], optional = true }

[target.'cfg(target_arch = "riscv32")'.dependencies]
esp-riscv-rt = { version = "0.9.0", path = "../esp-riscv-rt" }
Expand Down
207 changes: 123 additions & 84 deletions esp-hal/MIGRATING-0.21.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ 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 constructor changes
## I2C changes

The I2C master driver and related types have been moved to `esp_hal::i2c::master`.

The `with_timeout` constructors have been removed in favour of `set_timeout` or `with_timeout`.

Expand All @@ -97,12 +99,129 @@ The `with_timeout` constructors have been removed in favour of `set_timeout` or
+let i2c = I2c::new(peripherals.I2C0, io.pins.gpio4, io.pins.gpio5, 100.kHz()).with_timeout(timeout);
```

## Changes to half-duplex SPI
### I2C drivers can now be configured using `i2c::master::Config`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff looks quite goofy, but I'm trusting that you've just been rearranging some things and that it is correct.

Copy link
Contributor Author

@bugadani bugadani Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm not that confident (I mean the changes are OK, the reason behind them is shaky). I couldn't decide how to organize things, and I think per-peripheral is better than per-topic (e.g. config changes, constructor changes, etc.).


- The old methods to change configuration have been removed.
- The `new` and `new_typed` constructor no longer takes `frequency` and pins.
- The default configuration is now:
- bus frequency: 100 kHz
- timeout: about 10 bus clock cycles
- There are new constructors (`new_with_config`, `new_typed_with_config`) and a new `apply_config` method to apply custom configuration.
- Pins can now be configured using `with_sda` and `with_scl`

```diff
-use esp_hal::i2c::I2c;
+use esp_hal::i2c::master::{Config, I2c};
-I2c::new(I2C0, sda, scl, 100.kHz());
+I2c::new_with_config(
+ I2C0,
+ Config {
+ frequency: 400.kHz(),
+ ..Config::default()
+ },
+)
+.with_sda(sda)
+.with_scl(scl);
```

### 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.

## UART changes

### The `uart::config` module has been removed

The module's contents have been moved into `uart`.

```diff
-use esp_hal::uart::config::Config;
+use esp_hal::uart::Config;
```

If you work with multiple configurable peripherals, you may want to import the `uart` module and
refer to the `Config` struct as `uart::Config`.

### 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](https://docs.rs/enumset/1.1.5/enumset/index.html). For example, to see if
a particular interrupt bit is set, use `contains`:

```diff
-serial.at_cmd_interrupt_set()
+serial.interupts().contains(UartInterrupt::AtCmd)
```

You can now listen/unlisten multiple interrupt bits at once:

```diff
-uart0.listen_at_cmd();
-uart0.listen_rx_fifo_full();
+uart0.listen(UartInterrupt::AtCmd | UartConterrupt::RxFifoFull);
```

## SPI changes

### SPI drivers can now be configured using `spi::master::Config`

- The old methods to change configuration have been removed.
- The `new` and `new_typed` constructor no longer takes `frequency` and `mode`.
- The default configuration is now:
- bus frequency: 1 MHz
- bit order: MSB first
- mode: SPI mode 0
- There are new constructors (`new_with_config`, `new_typed_with_config`) and a new `apply_config` method to apply custom configuration.

```diff
-use esp_hal::spi::{master::Spi, SpiMode};
+use esp_hal::spi::{master::{Config, Spi}, SpiMode};
-Spi::new(SPI2, 100.kHz(), SpiMode::Mode1);
+Spi::new_with_config(
+ SPI2,
+ Config {
+ frequency: 100.kHz(),
+ mode: SpiMode::Mode0,
+ ..Config::default()
+ },
+)
```

### Half-duplex SPI type signature

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
### Half-duplex SPI driver construction

- The `Spi::new_half_duplex` constructor has been removed. Use `new` (or `new_typed`) instead.
- The `with_pins` methods have been removed. Use the individual `with_*` functions instead.
Expand All @@ -121,7 +240,7 @@ drivers. It is now possible to execute half-duplex and full-duplex operations on
+ .with_sio3(sio3);
```

### Transfer functions
### Half-duplex SPI transfer functions

The `Spi<'_, SPI, HalfDuplexMode>::read` and `Spi<'_, SPI, HalfDuplexMode>::write` functions have been replaced by
`half_duplex_read` and `half_duplex_write`.
Expand Down Expand Up @@ -154,48 +273,6 @@ The `Spi<'_, SPI, HalfDuplexMode>::read` and `Spi<'_, SPI, HalfDuplexMode>::writ
.unwrap();
```

## 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](https://docs.rs/enumset/1.1.5/enumset/index.html). For example, to see if
a particular interrupt bit is set, use `contains`:

```diff
-serial.at_cmd_interrupt_set()
+serial.interupts().contains(UartInterrupt::AtCmd)
```

You can now listen/unlisten multiple interrupt bits at once:

```diff
-uart0.listen_at_cmd();
-uart0.listen_rx_fifo_full();
+uart0.listen(UartInterrupt::AtCmd | UartConterrupt::RxFifoFull);
```

## Circular DMA transfer's `available` returns `Result<usize, DmaError>` now

In case of any error you should drop the transfer and restart it.
Expand Down Expand Up @@ -238,41 +315,3 @@ the GPIO drivers (`Input`, `Output`, `OutputOpenDrain` and `Flex`) instead.
(e.g. `use esp_hal::gpio::etm::Event as GpioEtmEvent`).
- The old task and event types have been replaced by `Task` and `Event`.
- GPIO tasks and events are no longer generic.

## Changes to peripheral configuration

### The `uart::config` module has been removed

The module's contents have been moved into `uart`.

```diff
-use esp_hal::uart::config::Config;
+use esp_hal::uart::Config;
```

If you work with multiple configurable peripherals, you may want to import the `uart` module and
refer to the `Config` struct as `uart::Config`.

### SPI drivers can now be configured using `spi::master::Config`

- The old methods to change configuration have been removed.
- The `new` and `new_typed` constructor no longer takes `frequency` and `mode`.
- The default configuration is now:
- bus frequency: 1 MHz
- bit order: MSB first
- mode: SPI mode 0
- There are new constructors (`new_with_config`, `new_typed_with_config`) and a new `apply_config` method to apply custom configuration.

```diff
-use esp_hal::spi::{master::Spi, SpiMode};
+use esp_hal::spi::{master::{Config, Spi}, SpiMode};
-Spi::new(SPI2, 100.kHz(), SpiMode::Mode1);
+Spi::new_with_config(
+ SPI2,
+ Config {
+ frequency: 100.kHz(),
+ mode: SpiMode::Mode0,
+ ..Config::default()
+ },
+)
```
Loading