improve SPI module #17

Merged
muellerr merged 1 commits from improve-spi-module into main 2026-04-02 23:22:38 +02:00
5 changed files with 50 additions and 12 deletions
+2 -2
View File
@@ -87,7 +87,7 @@ fn main() -> ! {
bmstall: true,
hw_cs: None,
};
spi.cfg_transfer(&transfer_cfg);
spi.configure_transfer(&transfer_cfg);
}
SpiBusSelect::SpiBPortB => {
let hw_cs_pin = configure_pin_as_hw_cs_pin(pinsb.pb2);
@@ -99,7 +99,7 @@ fn main() -> ! {
bmstall: true,
hw_cs: Some(hw_cs_pin),
};
spi.cfg_transfer(&transfer_cfg);
spi.configure_transfer(&transfer_cfg);
}
}
@@ -47,7 +47,7 @@ fn main() -> ! {
.mode(MODE_3)
.slave_output_disable(true);
let mut spi = Spi::new_for_spi1(dp.spib, (sck, miso, mosi), spi_cfg);
spi.cfg_hw_cs(hw_cs_id);
spi.configure_hw_cs(hw_cs_id);
let mut tx_rx_buf: [u8; 3] = [0; 3];
tx_rx_buf[0] = READ_MASK | DEVID_REG;
+2 -2
View File
@@ -83,7 +83,7 @@ impl<Delay: DelayNs> SpiDevice for SpiWithHwCs<Delay> {
) -> Result<(), Self::Error> {
// Only the HW CS is configured here. This is not really necessary, but showcases
// that we could scale this multiple SPI devices.
self.inner.cfg_hw_cs(self.hw_cs_id);
self.inner.configure_hw_cs(self.hw_cs_id);
for operation in operations {
match operation {
spi::Operation::Read(buf) => self.inner.read(buf),
@@ -93,7 +93,7 @@ impl<Delay: DelayNs> SpiDevice for SpiWithHwCs<Delay> {
spi::Operation::DelayNs(delay) => self.delay_provider.delay_ns(*delay),
};
}
self.inner.cfg_hw_cs_disable();
self.inner.disable_hw_cs();
Ok(())
}
}
+2
View File
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Add `is_high` and `is_low` for `InputPinAsync`.
- Add `InputPin` impl for `InputPinAsync`.
- `HwCsPin` in SPI module for easer usage of HW CS pins as `Output` CS pins
### Changed
@@ -19,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Renamed UART `Data` register `value` field to `data`
- Improved type level support for resource management for SPI, PWM, UART.
- Renamed `tx_asynch` and `rx_asynch` module name to `*_async`
- Naming improvements in SPI module: replaced `cfg` by `config*`
### Fixed
+43 -7
View File
@@ -676,14 +676,14 @@ where
}
#[inline]
pub fn cfg_clock_from_div(&mut self, div: u16) -> Result<(), SpiClockConfigError> {
pub fn configure_clock_from_div(&mut self, div: u16) -> Result<(), SpiClockConfigError> {
let val = spi_clk_config_from_div(div)?;
self.cfg_clock(val);
Ok(())
}
#[inline]
pub fn cfg_mode(&mut self, mode: Mode) {
pub fn configure_mode(&mut self, mode: Mode) {
let (cpo_bit, cph_bit) = mode_to_cpo_cph_bit(mode);
self.regs.modify_ctrl0(|mut value| {
value.set_spo(cpo_bit);
@@ -718,7 +718,7 @@ where
}
#[inline]
pub fn perid(&self) -> u32 {
pub fn peripheral_id(&self) -> u32 {
self.regs.read_perid()
}
@@ -728,7 +728,7 @@ where
/// by using the [configure_pin_as_hw_cs_pin] function which also returns the
/// corresponding [HwChipSelectId].
#[inline]
pub fn cfg_hw_cs(&mut self, hw_cs: HwChipSelectId) {
pub fn configure_hw_cs(&mut self, hw_cs: HwChipSelectId) {
self.regs.modify_ctrl1(|mut value| {
value.set_sod(false);
value.set_ss(hw_cs);
@@ -739,7 +739,7 @@ where
/// Disables the hardware chip select functionality. This can be used when performing
/// external chip select handling, for example with GPIO pins.
#[inline]
pub fn cfg_hw_cs_disable(&mut self) {
pub fn disable_hw_cs(&mut self) {
self.regs.modify_ctrl1(|mut value| {
value.set_sod(true);
value
@@ -749,12 +749,12 @@ where
/// Utility function to configure all relevant transfer parameters in one go.
/// This is useful if multiple devices with different clock and mode configurations
/// are connected to one bus.
pub fn cfg_transfer(&mut self, transfer_cfg: &TransferConfig) {
pub fn configure_transfer(&mut self, transfer_cfg: &TransferConfig) {
if let Some(trans_clk_div) = transfer_cfg.clk_cfg {
self.cfg_clock(trans_clk_div);
}
if let Some(mode) = transfer_cfg.mode {
self.cfg_mode(mode);
self.configure_mode(mode);
}
self.blockmode = transfer_cfg.blockmode;
self.regs.modify_ctrl1(|mut value| {
@@ -1057,3 +1057,39 @@ impl From<Spi<u16>> for Spi<u8> {
}
}
}
/// This abstraction which can be used to map a hardware chip select pin
/// to [embedded_hal::digital::OutputPin]. This is useful for creating physical chip select
/// pins required by the [embedded_hal_bus](https://docs.rs/embedded-hal-bus/latest/embedded_hal_bus/)
/// API.
pub struct HwCsPin {
regs: regs::MmioSpi<'static>,
id: HwChipSelectId,
}
impl HwCsPin {
pub fn new<P: HwCsProvider + AnyPin>(pin: P) -> Self {
configure_pin_as_hw_cs_pin(pin);
Self {
regs: unsafe { P::SPI_ID.steal_regs() },
id: P::CS_ID,
}
}
}
impl embedded_hal::digital::ErrorType for HwCsPin {
type Error = Infallible;
}
impl embedded_hal::digital::OutputPin for HwCsPin {
fn set_low(&mut self) -> Result<(), Self::Error> {
self.regs
.modify_ctrl1(|value| value.with_sod(false).with_ss(self.id));
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
self.regs.modify_ctrl1(|value| value.with_sod(true));
Ok(())
}
}