Interrupt flags

This commit is contained in:
ivmarkov 2023-05-13 10:07:38 +00:00
parent 01d35f3973
commit ba9cc4246a
11 changed files with 306 additions and 50 deletions

View File

@ -29,7 +29,7 @@ fn main() -> Result<()> {
// 3 seconds white at 10% brightness
neopixel(
RGB {
Rgb {
r: 25,
g: 25,
b: 25,
@ -51,7 +51,7 @@ fn main() -> Result<()> {
}
}
struct RGB {
struct Rgb {
r: u8,
g: u8,
b: u8,
@ -61,7 +61,7 @@ fn ns(nanos: u64) -> Duration {
Duration::from_nanos(nanos)
}
fn neopixel(rgb: RGB, tx: &mut TxRmtDriver) -> Result<()> {
fn neopixel(rgb: Rgb, tx: &mut TxRmtDriver) -> Result<()> {
// e.g. rgb: (1,2,4)
// G R B
// 7 0 7 0 7 0
@ -85,7 +85,7 @@ fn neopixel(rgb: RGB, tx: &mut TxRmtDriver) -> Result<()> {
}
/// Converts hue, saturation, value to RGB
fn hsv2rgb(h: u32, s: u32, v: u32) -> Result<RGB> {
fn hsv2rgb(h: u32, s: u32, v: u32) -> Result<Rgb> {
if h > 360 || s > 100 || v > 100 {
bail!("The given HSV values are not in valid range");
}
@ -99,19 +99,19 @@ fn hsv2rgb(h: u32, s: u32, v: u32) -> Result<RGB> {
r = c;
g = x;
b = 0.0;
} else if h >= 60 && h < 120 {
} else if (60..120).contains(&h) {
r = x;
g = c;
b = 0.0;
} else if h >= 120 && h < 180 {
} else if (120..180).contains(&h) {
r = 0.0;
g = c;
b = x;
} else if h >= 180 && h < 240 {
} else if (180..240).contains(&h) {
r = 0.0;
g = x;
b = c;
} else if h >= 240 && h < 300 {
} else if (240..300).contains(&h) {
r = x;
g = 0.0;
b = c;
@ -121,7 +121,7 @@ fn hsv2rgb(h: u32, s: u32, v: u32) -> Result<RGB> {
b = x;
}
Ok(RGB {
Ok(Rgb {
r: ((r + m) * 255.0) as u8,
g: ((g + m) * 255.0) as u8,
b: ((b + m) * 255.0) as u8,

View File

@ -32,7 +32,13 @@ fn main() -> anyhow::Result<()> {
println!("Starting SPI loopback test");
let driver = SpiDriver::new::<SPI2>(spi, sclk, serial_out, Some(serial_in), Dma::Disabled)?;
let driver = SpiDriver::new::<SPI2>(
spi,
sclk,
serial_out,
Some(serial_in),
&SpiDriverConfig::new(),
)?;
let config_1 = config::Config::new().baudrate(26.MHz().into());
let mut device_1 = SpiDeviceDriver::new(&driver, Some(cs_1), &config_1)?;

View File

@ -52,8 +52,15 @@ fn main() -> anyhow::Result<()> {
.baudrate(26.MHz().into())
.data_mode(MODE_3);
let device =
SpiDeviceDriver::new_single(spi, sclk, sda, Some(sdi), Dma::Disabled, Some(cs), &config)?;
let device = SpiDeviceDriver::new_single(
spi,
sclk,
sda,
Some(sdi),
Some(cs),
&SpiDriverConfig::new(),
&config,
)?;
// display interface abstraction from SPI and DC
let di = SPIInterfaceNoCS::new(device, dc);

View File

@ -36,6 +36,7 @@ use esp_idf_sys::*;
use crate::delay::{BLOCK, NON_BLOCK};
use crate::gpio::*;
use crate::interrupt::IntrFlags;
use crate::peripheral::{Peripheral, PeripheralRef};
crate::embedded_hal_error!(CanError, embedded_can::Error, embedded_can::ErrorKind);
@ -49,8 +50,11 @@ crate::embedded_hal_error!(
pub type CanConfig = config::Config;
pub mod config {
use enumset::EnumSet;
use esp_idf_sys::*;
use crate::interrupt::IntrFlags;
/// CAN timing
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Timing {
@ -433,7 +437,7 @@ pub mod config {
}
}
#[derive(Debug, Copy, Clone, Default)]
#[derive(Debug, Clone)]
pub struct Config {
pub timing: Timing,
pub filter: Filter,
@ -441,14 +445,19 @@ pub mod config {
pub rx_queue_len: u32,
pub mode: Mode,
pub alerts: Alerts,
pub intr_flags: EnumSet<IntrFlags>,
}
impl Config {
pub fn new() -> Self {
Config {
Self {
timing: Default::default(),
filter: Default::default(),
tx_queue_len: 5,
rx_queue_len: 5,
..Default::default()
mode: Default::default(),
alerts: Default::default(),
intr_flags: EnumSet::<IntrFlags>::empty(),
}
}
@ -464,25 +473,41 @@ pub mod config {
self
}
#[must_use]
pub fn tx_queue_len(mut self, tx_queue_len: u32) -> Self {
self.tx_queue_len = tx_queue_len;
self
}
#[must_use]
pub fn rx_queue_len(mut self, rx_queue_len: u32) -> Self {
self.rx_queue_len = rx_queue_len;
self
}
#[must_use]
pub fn mode(mut self, mode: Mode) -> Self {
self.mode = mode;
self
}
#[must_use]
pub fn alerts(mut self, alerts: Alerts) -> Self {
self.alerts = alerts;
self
}
#[must_use]
pub fn intr_flags(mut self, flags: EnumSet<IntrFlags>) -> Self {
self.intr_flags = flags;
self
}
}
impl Default for Config {
fn default() -> Self {
Self::new()
}
}
}
@ -510,7 +535,7 @@ impl<'d> CanDriver<'d> {
rx_queue_len: config.rx_queue_len,
alerts_enabled: config.alerts.into(),
clkout_divider: 0,
intr_flags: ESP_INTR_FLAG_LEVEL1 as i32,
intr_flags: IntrFlags::to_native(config.intr_flags) as _,
};
let timing_config = config.timing.into();

View File

@ -1319,22 +1319,33 @@ impl UnsafeCallback {
}
}
#[cfg(all(not(feature = "riscv-ulp-hal"), feature = "alloc"))]
#[cfg(not(feature = "riscv-ulp-hal"))]
static ISR_ALLOC_FLAGS: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
#[cfg(not(feature = "riscv-ulp-hal"))]
static ISR_SERVICE_ENABLED: core::sync::atomic::AtomicBool =
core::sync::atomic::AtomicBool::new(false);
#[cfg(all(not(feature = "riscv-ulp-hal"), feature = "alloc"))]
#[cfg(not(feature = "riscv-ulp-hal"))]
static ISR_SERVICE_ENABLED_CS: crate::task::CriticalSection = crate::task::CriticalSection::new();
#[cfg(all(not(feature = "riscv-ulp-hal"), feature = "alloc"))]
fn enable_isr_service() -> Result<(), EspError> {
#[cfg(not(feature = "riscv-ulp-hal"))]
pub fn init_isr_alloc_flags(flags: enumset::EnumSet<crate::interrupt::IntrFlags>) {
ISR_ALLOC_FLAGS.store(
crate::interrupt::IntrFlags::to_native(flags),
core::sync::atomic::Ordering::SeqCst,
);
}
#[cfg(not(feature = "riscv-ulp-hal"))]
pub fn enable_isr_service() -> Result<(), EspError> {
use core::sync::atomic::Ordering;
if !ISR_SERVICE_ENABLED.load(Ordering::SeqCst) {
let _guard = ISR_SERVICE_ENABLED_CS.enter();
if !ISR_SERVICE_ENABLED.load(Ordering::SeqCst) {
esp!(unsafe { gpio_install_isr_service(0) })?;
esp!(unsafe { gpio_install_isr_service(ISR_ALLOC_FLAGS.load(Ordering::SeqCst) as _) })?;
ISR_SERVICE_ENABLED.store(true, Ordering::SeqCst);
}

View File

@ -7,6 +7,7 @@ use esp_idf_sys::*;
use crate::delay::*;
use crate::gpio::*;
use crate::interrupt::IntrFlags;
use crate::peripheral::Peripheral;
use crate::units::*;
@ -36,16 +37,19 @@ pub type I2cSlaveConfig = config::SlaveConfig;
/// I2C configuration
pub mod config {
use enumset::EnumSet;
use super::APBTickType;
use crate::units::*;
use crate::{interrupt::IntrFlags, units::*};
/// I2C Master configuration
#[derive(Copy, Clone)]
#[derive(Debug, Clone)]
pub struct Config {
pub baudrate: Hertz,
pub sda_pullup_enabled: bool,
pub scl_pullup_enabled: bool,
pub timeout: Option<APBTickType>,
pub intr_flags: EnumSet<IntrFlags>,
}
impl Config {
@ -76,6 +80,12 @@ pub mod config {
self.timeout = Some(timeout);
self
}
#[must_use]
pub fn intr_flags(mut self, flags: EnumSet<IntrFlags>) -> Self {
self.intr_flags = flags;
self
}
}
impl Default for Config {
@ -85,18 +95,20 @@ pub mod config {
sda_pullup_enabled: true,
scl_pullup_enabled: true,
timeout: None,
intr_flags: EnumSet::<IntrFlags>::empty(),
}
}
}
/// I2C Slave configuration
#[cfg(not(esp32c2))]
#[derive(Copy, Clone)]
#[derive(Debug, Clone)]
pub struct SlaveConfig {
pub sda_pullup_enabled: bool,
pub scl_pullup_enabled: bool,
pub rx_buf_len: usize,
pub tx_buf_len: usize,
pub intr_flags: EnumSet<IntrFlags>,
}
#[cfg(not(esp32c2))]
@ -128,6 +140,12 @@ pub mod config {
self.tx_buf_len = len;
self
}
#[must_use]
pub fn intr_flags(mut self, flags: EnumSet<IntrFlags>) -> Self {
self.intr_flags = flags;
self
}
}
#[cfg(not(esp32c2))]
@ -138,6 +156,7 @@ pub mod config {
scl_pullup_enabled: true,
rx_buf_len: 0,
tx_buf_len: 0,
intr_flags: EnumSet::<IntrFlags>::empty(),
}
}
}
@ -188,8 +207,8 @@ impl<'d> I2cDriver<'d> {
i2c_mode_t_I2C_MODE_MASTER,
0, // Not used in master mode
0, // Not used in master mode
0,
) // TODO: set flags
IntrFlags::to_native(config.intr_flags) as _,
)
})?;
if let Some(timeout) = config.timeout {
@ -460,7 +479,7 @@ impl<'d> I2cSlaveDriver<'d> {
i2c_mode_t_I2C_MODE_SLAVE,
config.rx_buf_len,
config.tx_buf_len,
0, // TODO: set flags
IntrFlags::to_native(config.intr_flags) as _,
)
})?;

View File

@ -1,7 +1,82 @@
use core::sync::atomic::{AtomicU64, Ordering};
use enumset::{EnumSet, EnumSetType};
use esp_idf_sys::*;
/// Interrupt allocation flags.
/// These flags can be used to specify which interrupt qualities the code calling esp_intr_alloc* needs.
#[derive(Debug, EnumSetType)]
pub enum IntrFlags {
// Accept a Level 1 interrupt vector (lowest priority)
Level1,
// Accept a Level 2 interrupt vector.
Level2,
// Accept a Level 3 interrupt vector.
Level3,
// Accept a Level 4 interrupt vector.
Level4,
// Accept a Level 5 interrupt vector.
Level5,
// Accept a Level 6 interrupt vector.
Level6,
// Accept a Level 7 interrupt vector (highest priority)
Nmi,
// Interrupt can be shared between ISRs.
Shared,
// Edge-triggered interrupt.
Edge,
// ISR can be called if cache is disabled.
// Must be used with a proper option *_ISR_IN_IRAM in SDKCONFIG
Iram,
// Return with this interrupt disabled.
IntrDisabled,
// Low and medium prio interrupts. These can be handled in C.
LowMed,
// High level interrupts. Need to be handled in assembly.
High,
}
impl IntrFlags {
pub fn levels(&self) -> EnumSet<Self> {
Self::Level1
| Self::Level2
| Self::Level3
| Self::Level4
| Self::Level5
| Self::Level6
| Self::Nmi
}
pub(crate) fn to_native(flags: EnumSet<Self>) -> u32 {
let mut uflags: u32 = 0;
for flag in flags {
uflags |= u32::from(flag);
}
uflags
}
}
impl From<IntrFlags> for u32 {
fn from(flag: IntrFlags) -> Self {
match flag {
IntrFlags::Level1 => esp_idf_sys::ESP_INTR_FLAG_LEVEL1,
IntrFlags::Level2 => esp_idf_sys::ESP_INTR_FLAG_LEVEL2,
IntrFlags::Level3 => esp_idf_sys::ESP_INTR_FLAG_LEVEL3,
IntrFlags::Level4 => esp_idf_sys::ESP_INTR_FLAG_LEVEL4,
IntrFlags::Level5 => esp_idf_sys::ESP_INTR_FLAG_LEVEL5,
IntrFlags::Level6 => esp_idf_sys::ESP_INTR_FLAG_LEVEL6,
IntrFlags::Nmi => esp_idf_sys::ESP_INTR_FLAG_NMI,
IntrFlags::Shared => esp_idf_sys::ESP_INTR_FLAG_SHARED,
IntrFlags::Edge => esp_idf_sys::ESP_INTR_FLAG_EDGE,
IntrFlags::Iram => esp_idf_sys::ESP_INTR_FLAG_IRAM,
IntrFlags::IntrDisabled => esp_idf_sys::ESP_INTR_FLAG_INTRDISABLED,
IntrFlags::LowMed => esp_idf_sys::ESP_INTR_FLAG_LOWMED,
IntrFlags::High => esp_idf_sys::ESP_INTR_FLAG_HIGH,
}
}
}
pub(crate) static CS: IsrCriticalSection = IsrCriticalSection::new();
/// Returns true if the currently active core is executing an ISR request

View File

@ -515,6 +515,8 @@ impl Drop for PcntDriver<'_> {
}
}
static ISR_ALLOC_FLAGS: core::sync::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
#[cfg(feature = "alloc")]
static ISR_SERVICE_ENABLED: core::sync::atomic::AtomicBool =
core::sync::atomic::AtomicBool::new(false);
@ -522,6 +524,13 @@ static ISR_SERVICE_ENABLED: core::sync::atomic::AtomicBool =
#[cfg(feature = "alloc")]
static PCNT_CS: crate::task::CriticalSection = crate::task::CriticalSection::new();
pub fn init_isr_alloc_flags(flags: enumset::EnumSet<crate::interrupt::IntrFlags>) {
ISR_ALLOC_FLAGS.store(
crate::interrupt::IntrFlags::to_native(flags),
core::sync::atomic::Ordering::SeqCst,
);
}
#[cfg(feature = "alloc")]
fn enable_isr_service() -> Result<(), EspError> {
use core::sync::atomic::Ordering;
@ -530,7 +539,7 @@ fn enable_isr_service() -> Result<(), EspError> {
let _cs = PCNT_CS.enter();
if !ISR_SERVICE_ENABLED.load(Ordering::SeqCst) {
esp!(unsafe { pcnt_isr_service_install(0) })?;
esp!(unsafe { pcnt_isr_service_install(ISR_ALLOC_FLAGS.load(Ordering::SeqCst) as _) })?;
ISR_SERVICE_ENABLED.store(true, Ordering::SeqCst);
}

View File

@ -64,6 +64,7 @@ use esp_idf_sys::*;
use crate::gpio::InputPin;
use crate::gpio::OutputPin;
use crate::interrupt::IntrFlags;
use crate::peripheral::Peripheral;
use crate::units::Hertz;
@ -250,10 +251,14 @@ pub type RxRmtConfig = config::ReceiveConfig;
///
/// ```
pub mod config {
use enumset::EnumSet;
use esp_idf_sys::{EspError, ESP_ERR_INVALID_ARG};
use super::PinState;
use crate::units::{FromValueType, Hertz};
use crate::{
interrupt::IntrFlags,
units::{FromValueType, Hertz},
};
/// A percentage from 0 to 100%, used to specify the duty percentage in [`CarrierConfig`].
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@ -292,16 +297,19 @@ pub mod config {
}
}
#[must_use]
pub fn frequency(mut self, hz: Hertz) -> Self {
self.frequency = hz;
self
}
#[must_use]
pub fn carrier_level(mut self, state: PinState) -> Self {
self.carrier_level = state;
self
}
#[must_use]
pub fn duty_percent(mut self, duty: DutyPercent) -> Self {
self.duty_percent = duty;
self
@ -329,6 +337,7 @@ pub mod config {
}
/// Used when creating a [`Transmit`][crate::rmt::Transmit] instance.
#[derive(Debug, Clone)]
pub struct TransmitConfig {
pub clock_divider: u8,
pub mem_block_num: u8,
@ -344,6 +353,8 @@ pub mod config {
/// When set, RMT channel will take REF_TICK or XTAL as source clock. The benefit is, RMT
/// channel can continue work even when APB clock is changing.
pub aware_dfs: bool,
pub intr_flags: EnumSet<IntrFlags>,
}
impl TransmitConfig {
@ -355,38 +366,51 @@ pub mod config {
looping: Loop::None,
carrier: None,
idle: Some(PinState::Low),
intr_flags: EnumSet::<IntrFlags>::empty(),
}
}
#[must_use]
pub fn aware_dfs(mut self, enable: bool) -> Self {
self.aware_dfs = enable;
self
}
#[must_use]
pub fn mem_block_num(mut self, mem_block_num: u8) -> Self {
self.mem_block_num = mem_block_num;
self
}
#[must_use]
pub fn clock_divider(mut self, divider: u8) -> Self {
self.clock_divider = divider;
self
}
#[must_use]
pub fn looping(mut self, looping: Loop) -> Self {
self.looping = looping;
self
}
#[must_use]
pub fn carrier(mut self, carrier: Option<CarrierConfig>) -> Self {
self.carrier = carrier;
self
}
#[must_use]
pub fn idle(mut self, idle: Option<PinState>) -> Self {
self.idle = idle;
self
}
#[must_use]
pub fn intr_flags(mut self, flags: EnumSet<IntrFlags>) -> Self {
self.intr_flags = flags;
self
}
}
impl Default for TransmitConfig {
@ -397,6 +421,7 @@ pub mod config {
}
/// Used when creating a [`Receive`][crate::rmt::Receive] instance.
#[derive(Debug, Clone)]
pub struct ReceiveConfig {
pub clock_divider: u8,
pub mem_block_num: u8,
@ -404,6 +429,7 @@ pub mod config {
pub filter_ticks_thresh: u8,
pub filter_en: bool,
pub carrier: Option<CarrierConfig>,
pub intr_flags: EnumSet<IntrFlags>,
}
impl ReceiveConfig {
@ -411,35 +437,47 @@ pub mod config {
Self::default()
}
#[must_use]
pub fn clock_divider(mut self, divider: u8) -> Self {
self.clock_divider = divider;
self
}
#[must_use]
pub fn mem_block_num(mut self, mem_block_num: u8) -> Self {
self.mem_block_num = mem_block_num;
self
}
#[must_use]
pub fn idle_threshold(mut self, threshold: u16) -> Self {
self.idle_threshold = threshold;
self
}
#[must_use]
pub fn filter_ticks_thresh(mut self, threshold: u8) -> Self {
self.filter_ticks_thresh = threshold;
self
}
#[must_use]
pub fn filter_en(mut self, enable: bool) -> Self {
self.filter_en = enable;
self
}
#[must_use]
pub fn carrier(mut self, carrier: Option<CarrierConfig>) -> Self {
self.carrier = carrier;
self
}
#[must_use]
pub fn intr_flags(mut self, flags: EnumSet<IntrFlags>) -> Self {
self.intr_flags = flags;
self
}
}
impl Default for ReceiveConfig {
@ -452,6 +490,7 @@ pub mod config {
filter_ticks_thresh: 100, // 100 microseconds, pulses less than this will be ignored
filter_en: true,
carrier: None,
intr_flags: EnumSet::<IntrFlags>::empty(),
}
}
}
@ -520,7 +559,11 @@ impl<'d> TxRmtDriver<'d> {
unsafe {
esp!(rmt_config(&sys_config))?;
esp!(rmt_driver_install(C::channel(), 0, 0))?;
esp!(rmt_driver_install(
C::channel(),
0,
IntrFlags::to_native(config.intr_flags) as _
))?;
}
Ok(Self {
@ -943,7 +986,7 @@ impl<'d> RxRmtDriver<'d> {
#[cfg(not(any(esp32, esp32c2)))]
let carrier = config.carrier.unwrap_or_default();
let config = rmt_config_t {
let sys_config = rmt_config_t {
rmt_mode: rmt_mode_t_RMT_MODE_RX,
channel: C::channel(),
gpio_num: pin.pin(),
@ -968,8 +1011,12 @@ impl<'d> RxRmtDriver<'d> {
};
unsafe {
esp!(rmt_config(&config))?;
esp!(rmt_driver_install(C::channel(), ring_buf_size * 4, 0))?;
esp!(rmt_config(&sys_config))?;
esp!(rmt_driver_install(
C::channel(),
ring_buf_size * 4,
IntrFlags::to_native(config.intr_flags) as _
))?;
}
Ok(Self {

View File

@ -45,6 +45,7 @@ use esp_idf_sys::*;
use crate::delay::{Ets, BLOCK};
use crate::gpio::{AnyOutputPin, InputPin, Level, Output, OutputPin, PinDriver};
use crate::interrupt::IntrFlags;
use crate::peripheral::Peripheral;
use crate::task::CriticalSection;
@ -96,13 +97,17 @@ impl Dma {
}
}
pub type SpiDriverConfig = config::DriverConfig;
pub type SpiConfig = config::Config;
/// SPI configuration
pub mod config {
use crate::units::*;
use crate::{interrupt::IntrFlags, units::*};
use enumset::EnumSet;
use esp_idf_sys::*;
use super::Dma;
pub struct V02Type<T>(pub T);
impl From<V02Type<embedded_hal_0_2::spi::Polarity>> for embedded_hal::spi::Polarity {
@ -137,7 +142,7 @@ pub mod config {
}
/// Specify the communication mode with the device
#[derive(Copy, Clone)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Duplex {
/// Full duplex is the default
Full,
@ -158,7 +163,7 @@ pub mod config {
}
/// Specifies the order in which the bits of data should be transfered/received
#[derive(Copy, Clone)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BitOrder {
/// Most significant bit first (default)
MsbFirst,
@ -181,8 +186,42 @@ pub mod config {
}
}
/// SPI Driver configuration
#[derive(Debug, Clone)]
pub struct DriverConfig {
pub dma: Dma,
pub intr_flags: EnumSet<IntrFlags>,
}
impl DriverConfig {
pub fn new() -> Self {
Default::default()
}
#[must_use]
pub fn dma(mut self, dma: Dma) -> Self {
self.dma = dma;
self
}
#[must_use]
pub fn intr_flags(mut self, intr_flags: EnumSet<IntrFlags>) -> Self {
self.intr_flags = intr_flags;
self
}
}
impl Default for DriverConfig {
fn default() -> Self {
Self {
dma: Dma::Disabled,
intr_flags: EnumSet::<IntrFlags>::empty(),
}
}
}
/// SPI Device configuration
#[derive(Copy, Clone)]
#[derive(Debug, Clone)]
pub struct Config {
pub baudrate: Hertz,
pub data_mode: embedded_hal::spi::Mode,
@ -214,26 +253,31 @@ pub mod config {
self
}
#[must_use]
pub fn write_only(mut self, write_only: bool) -> Self {
self.write_only = write_only;
self
}
#[must_use]
pub fn duplex(mut self, duplex: Duplex) -> Self {
self.duplex = duplex;
self
}
#[must_use]
pub fn bit_order(mut self, bit_order: BitOrder) -> Self {
self.bit_order = bit_order;
self
}
#[must_use]
pub fn cs_active_high(mut self) -> Self {
self.cs_active_high = true;
self
}
#[must_use]
pub fn input_delay_ns(mut self, input_delay_ns: i32) -> Self {
self.input_delay_ns = input_delay_ns;
self
@ -476,9 +520,9 @@ impl<'d> SpiDriver<'d> {
sclk: impl Peripheral<P = crate::gpio::Gpio6> + 'd,
sdo: impl Peripheral<P = crate::gpio::Gpio7> + 'd,
sdi: Option<impl Peripheral<P = crate::gpio::Gpio8> + 'd>,
dma: Dma,
config: &config::DriverConfig,
) -> Result<Self, EspError> {
let max_transfer_size = Self::new_internal(SPI1::device(), sclk, sdo, sdi, dma)?;
let max_transfer_size = Self::new_internal(SPI1::device(), sclk, sdo, sdi, config)?;
Ok(Self {
host: SPI1::device() as _,
@ -493,9 +537,9 @@ impl<'d> SpiDriver<'d> {
sclk: impl Peripheral<P = impl OutputPin> + 'd,
sdo: impl Peripheral<P = impl OutputPin> + 'd,
sdi: Option<impl Peripheral<P = impl InputPin + OutputPin> + 'd>,
dma: Dma,
config: &config::DriverConfig,
) -> Result<Self, EspError> {
let max_transfer_size = Self::new_internal(SPI::device(), sclk, sdo, sdi, dma)?;
let max_transfer_size = Self::new_internal(SPI::device(), sclk, sdo, sdi, config)?;
Ok(Self {
host: SPI::device() as _,
@ -513,14 +557,15 @@ impl<'d> SpiDriver<'d> {
sclk: impl Peripheral<P = impl OutputPin> + 'd,
sdo: impl Peripheral<P = impl OutputPin> + 'd,
sdi: Option<impl Peripheral<P = impl InputPin + OutputPin> + 'd>,
dma: Dma,
config: &config::DriverConfig,
) -> Result<usize, EspError> {
crate::into_ref!(sclk, sdo);
let sdi = sdi.map(|sdi| sdi.into_ref());
let max_transfer_sz = dma.max_transfer_size();
let dma_chan: spi_dma_chan_t = dma.into();
let max_transfer_sz = config.dma.max_transfer_size();
let dma_chan: spi_dma_chan_t = config.dma.into();
#[allow(clippy::needless_update)]
#[cfg(not(esp_idf_version = "4.3"))]
let bus_config = spi_bus_config_t {
flags: SPICOMMON_BUSFLAG_MASTER,
@ -547,9 +592,11 @@ impl<'d> SpiDriver<'d> {
//data3_io_num: -1,
},
max_transfer_sz: max_transfer_sz as i32,
intr_flags: IntrFlags::to_native(config.intr_flags) as _,
..Default::default()
};
#[allow(clippy::needless_update)]
#[cfg(esp_idf_version = "4.3")]
let bus_config = spi_bus_config_t {
flags: SPICOMMON_BUSFLAG_MASTER,
@ -561,6 +608,7 @@ impl<'d> SpiDriver<'d> {
quadhd_io_num: -1,
max_transfer_sz: max_transfer_sz as i32,
intr_flags: config.intr_flags.into() as _,
..Default::default()
};
@ -594,11 +642,15 @@ impl<'d> SpiDeviceDriver<'d, SpiDriver<'d>> {
sclk: impl Peripheral<P = crate::gpio::Gpio6> + 'd,
sdo: impl Peripheral<P = crate::gpio::Gpio7> + 'd,
sdi: Option<impl Peripheral<P = crate::gpio::Gpio8> + 'd>,
dma: Dma,
cs: Option<impl Peripheral<P = impl OutputPin> + 'd>,
bus_config: &config::DriverConfig,
config: &config::Config,
) -> Result<Self, EspError> {
Self::new(SpiDriver::new_spi1(spi, sclk, sdo, sdi, dma)?, cs, config)
Self::new(
SpiDriver::new_spi1(spi, sclk, sdo, sdi, bus_config)?,
cs,
config,
)
}
pub fn new_single<SPI: SpiAnyPins>(
@ -606,11 +658,11 @@ impl<'d> SpiDeviceDriver<'d, SpiDriver<'d>> {
sclk: impl Peripheral<P = impl OutputPin> + 'd,
sdo: impl Peripheral<P = impl OutputPin> + 'd,
sdi: Option<impl Peripheral<P = impl InputPin + OutputPin> + 'd>,
dma: Dma,
cs: Option<impl Peripheral<P = impl OutputPin> + 'd>,
bus_config: &config::DriverConfig,
config: &config::Config,
) -> Result<Self, EspError> {
Self::new(SpiDriver::new(spi, sclk, sdo, sdi, dma)?, cs, config)
Self::new(SpiDriver::new(spi, sclk, sdo, sdi, bus_config)?, cs, config)
}
}

View File

@ -44,6 +44,7 @@ use core::sync::atomic::{AtomicU8, Ordering};
use crate::delay::NON_BLOCK;
use crate::gpio::*;
use crate::interrupt::IntrFlags;
use crate::units::*;
use esp_idf_sys::*;
@ -56,7 +57,8 @@ pub type UartConfig = config::Config;
/// UART configuration
pub mod config {
use crate::units::*;
use crate::{interrupt::IntrFlags, units::*};
use enumset::EnumSet;
use esp_idf_sys::*;
/// Number of data bits
@ -299,7 +301,7 @@ pub mod config {
}
/// UART configuration
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Clone)]
pub struct Config {
pub baudrate: Hertz,
pub data_bits: DataBits,
@ -308,6 +310,7 @@ pub mod config {
pub flow_control: FlowControl,
pub flow_control_rts_threshold: u8,
pub source_clock: SourceClock,
pub intr_flags: EnumSet<IntrFlags>,
}
impl Config {
@ -383,6 +386,7 @@ pub mod config {
flow_control: FlowControl::None,
flow_control_rts_threshold: 122,
source_clock: SourceClock::default(),
intr_flags: EnumSet::<IntrFlags>::empty(),
}
}
}
@ -934,6 +938,7 @@ fn new_common<UART: Uart>(
};
esp!(unsafe { uart_param_config(UART::port(), &uart_config) })?;
esp!(unsafe { uart_intr_config(UART::port(), IntrFlags::to_native(config.intr_flags) as _) })?;
esp!(unsafe {
uart_set_pin(