Skip to content

Commit

Permalink
apply_config
Browse files Browse the repository at this point in the history
  • Loading branch information
bugadani committed Nov 5, 2024
1 parent 233bd44 commit 7408f9c
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 63 deletions.
3 changes: 3 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `{Uart, UartRx, UartTx}::apply_config()` (#2449)
- `{Uart, UartRx, UartTx}` now implement `embassy_embedded_hal::SetConfig` (#2449)
- GPIO ETM tasks and events now accept `InputSignal` and `OutputSignal` (#2427)
- `spi::master::Config` and `{Spi, SpiDma, SpiDmaBus}::apply_config` (#2448)

### Changed

Expand All @@ -50,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `rmt::asynch::RxChannelAsync` and `rmt::asynch::TxChannelAsync` traits have been moved to `rmt` (#2430)
- Calling `AnyPin::output_signals` on an input-only pin (ESP32 GPIO 34-39) will now result in a panic. (#2418)
- 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)

### Fixed

Expand Down Expand Up @@ -85,6 +87,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The `SysTimerEtm` prefix has been removed from `timer::systimer::etm` types (#2427)
- 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)

## [0.21.1]

Expand Down
12 changes: 11 additions & 1 deletion esp-hal/MIGRATING-0.21.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,4 +251,14 @@ The module's contents have been moved into `uart`.
```

If you work with multiple configurable peripherals, you may want to import the `uart` module and
refer to the `Config` struct as `uart::Config`.
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.
143 changes: 81 additions & 62 deletions esp-hal/src/spi/master.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,35 @@ impl Address {
}
}

/// SPI peripheral configuration
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Config {
/// SPI clock frequency
pub frequency: HertzU32,

/// SPI mode
pub mode: SpiMode,

/// Bit order of the read data.
pub read_bit_order: SpiBitOrder,

/// Bit order of the written data.
pub write_bit_order: SpiBitOrder,
}

impl Default for Config {
fn default() -> Self {
use fugit::RateExtU32;
Config {
frequency: 1_u32.MHz(),
mode: SpiMode::Mode0,
read_bit_order: SpiBitOrder::MSBFirst,
write_bit_order: SpiBitOrder::MSBFirst,
}
}
}

/// SPI peripheral driver
pub struct Spi<'d, M, T = AnySpi> {
spi: PeripheralRef<'d, T>,
Expand Down Expand Up @@ -503,12 +532,16 @@ where

impl<'d> Spi<'d, Blocking> {
/// Constructs an SPI instance in 8bit dataframe mode.
pub fn new(
pub fn new(spi: impl Peripheral<P = impl Instance> + 'd) -> Spi<'d, Blocking> {
Self::new_with_config(spi, Config::default())
}

/// Constructs an SPI instance in 8bit dataframe mode.
pub fn new_with_config(
spi: impl Peripheral<P = impl Instance> + 'd,
frequency: HertzU32,
mode: SpiMode,
config: Config,
) -> Spi<'d, Blocking> {
Self::new_typed(spi.map_into(), frequency, mode)
Self::new_typed_with_config(spi.map_into(), config)
}

/// Converts the SPI instance into async mode.
Expand All @@ -535,24 +568,27 @@ where
T: Instance,
{
/// Constructs an SPI instance in 8bit dataframe mode.
pub fn new_typed(
pub fn new_typed(spi: impl Peripheral<P = T> + 'd) -> Spi<'d, M, T> {
Self::new_typed_with_config(spi, Config::default())
}

/// Constructs an SPI instance in 8bit dataframe mode.
pub fn new_typed_with_config(
spi: impl Peripheral<P = T> + 'd,
frequency: HertzU32,
mode: SpiMode,
config: Config,
) -> Spi<'d, M, T> {
crate::into_ref!(spi);

let this = Spi {
let mut this = Spi {
spi,
_mode: PhantomData,
};

PeripheralClockControl::enable(this.spi.peripheral());
PeripheralClockControl::reset(this.spi.peripheral());

this.driver().setup(frequency);
this.driver().init();
this.driver().set_data_mode(mode);
this.apply_config(&config);

let this = this
.with_mosi(NoPin)
Expand Down Expand Up @@ -635,20 +671,9 @@ where
self
}

/// Change the bus frequency of the SPI instance in half-duplex mode.
///
/// This method allows you to update the bus frequency for the SPI
/// communication after the instance has been created.
pub fn change_bus_frequency(&mut self, frequency: HertzU32) {
self.driver().ch_bus_freq(frequency);
}

/// Set the bit order for the SPI instance.
///
/// The default is MSB first for both read and write.
pub fn with_bit_order(self, read_order: SpiBitOrder, write_order: SpiBitOrder) -> Self {
self.driver().set_bit_order(read_order, write_order);
self
/// Change the bus configuration.
pub fn apply_config(&mut self, config: &Config) {
self.driver().apply_config(config);
}
}

Expand Down Expand Up @@ -865,6 +890,13 @@ mod dma {
address_buffer: DmaTxBuf,
}

impl<M, T> crate::private::Sealed for SpiDma<'_, M, T>
where
T: Instance,
M: Mode,
{
}

impl<'d, T> SpiDma<'d, Blocking, T>
where
T: Instance,
Expand Down Expand Up @@ -1152,23 +1184,10 @@ mod dma {
}
}
}
}

impl<M, T> crate::private::Sealed for SpiDma<'_, M, T>
where
T: Instance,
M: Mode,
{
}

impl<'d, M, T> SpiDma<'d, M, T>
where
T: Instance,
M: Mode,
{
/// Changes the SPI bus frequency for the DMA-enabled SPI instance.
pub fn change_bus_frequency(&mut self, frequency: HertzU32) {
self.driver().ch_bus_freq(frequency);
/// Change the bus configuration.
pub fn apply_config(&mut self, config: &Config) {
self.driver().apply_config(config);
}

/// Configures the DMA buffers for the SPI instance.
Expand Down Expand Up @@ -1487,6 +1506,13 @@ mod dma {
tx_buf: DmaTxBuf,
}

impl<M, T> crate::private::Sealed for SpiDmaBus<'_, M, T>
where
T: Instance,
M: Mode,
{
}

impl<'d, T> SpiDmaBus<'d, Blocking, T>
where
T: Instance,
Expand Down Expand Up @@ -1529,15 +1555,6 @@ mod dma {
tx_buf,
}
}

fn wait_for_idle(&mut self) {
self.spi_dma.wait_for_idle();
}

/// Changes the SPI bus frequency for the DMA-enabled SPI instance.
pub fn change_bus_frequency(&mut self, frequency: HertzU32) {
self.spi_dma.change_bus_frequency(frequency);
}
}

impl<T> InterruptConfigurable for SpiDmaBus<'_, Blocking, T>
Expand Down Expand Up @@ -1578,18 +1595,20 @@ mod dma {
}
}

impl<M, T> crate::private::Sealed for SpiDmaBus<'_, M, T>
where
T: Instance,
M: Mode,
{
}

impl<M, T> SpiDmaBus<'_, M, T>
where
T: Instance,
M: Mode,
{
fn wait_for_idle(&mut self) {
self.spi_dma.wait_for_idle();
}

/// Change the bus configuration.
pub fn apply_config(&mut self, config: &Config) {
self.spi_dma.apply_config(config);
}

/// Reads data from the SPI bus using DMA.
pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
self.wait_for_idle();
Expand Down Expand Up @@ -1683,13 +1702,7 @@ mod dma {

Ok(())
}
}

impl<M, T> SpiDmaBus<'_, M, T>
where
T: Instance,
M: Mode,
{
/// Half-duplex read.
pub fn half_duplex_read(
&mut self,
Expand Down Expand Up @@ -2560,6 +2573,12 @@ impl Info {
});
}

fn apply_config(&self, config: &Config) {
self.ch_bus_freq(config.frequency);
self.set_bit_order(config.read_bit_order, config.write_bit_order);
self.set_data_mode(config.mode);
}

fn set_data_mode(&self, data_mode: SpiMode) {
let reg_block = self.register_block();

Expand Down

0 comments on commit 7408f9c

Please sign in to comment.