1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Target-specific definitions

// Export HAL
#[cfg(feature = "stm32f0")]
pub use stm32f0xx_hal as hal;
#[cfg(feature = "stm32f1")]
pub use stm32f1xx_hal as hal;
#[cfg(feature = "stm32f3")]
pub use stm32f3xx_hal as hal;
#[cfg(feature = "stm32l0")]
pub use stm32l0xx_hal as hal;
#[cfg(feature = "stm32l4")]
pub use stm32l4xx_hal as hal;


// USB PAC reexports
#[cfg(feature = "stm32f0")]
pub use hal::stm32::USB;
#[cfg(feature = "stm32f1")]
pub use hal::stm32::USB;
#[cfg(feature = "stm32f3")]
pub use hal::stm32::USB;
#[cfg(feature = "stm32l0")]
pub use hal::stm32::USB;
#[cfg(feature = "stm32l4")]
pub use hal::stm32::USB;

// Use bundled register definitions instead of device-specific ones
// This should work because register definitions from newer chips seem to be
// compatible with definitions for older ones.
pub use crate::pac::usb;


#[cfg(feature = "ram_access_1x16")]
pub type UsbAccessType = u32;
#[cfg(feature = "ram_access_2x16")]
pub type UsbAccessType = u16;


#[cfg(not(feature = "ram_addr_40006c00"))]
pub const EP_MEM_ADDR: usize = 0x4000_6000;
#[cfg(feature = "ram_addr_40006c00")]
pub const EP_MEM_ADDR: usize = 0x4000_6C00;


#[cfg(feature = "ram_size_512")]
pub const EP_MEM_SIZE: usize = 512;
#[cfg(feature = "ram_size_1024")]
pub const EP_MEM_SIZE: usize = 1024;


pub const NUM_ENDPOINTS: usize = 8;


/// Enables USB peripheral
pub fn apb_usb_enable() {
    cortex_m::interrupt::free(|_| {
        let rcc = unsafe { (&*hal::stm32::RCC::ptr()) };
        match () {
            #[cfg(any(feature = "stm32f0", feature = "stm32f1", feature = "stm32f3", feature = "stm32l0"))]
            () => rcc.apb1enr.modify(|_, w| w.usben().set_bit()),
            #[cfg(feature = "stm32l4")]
            () => rcc.apb1enr1.modify(|_, w| w.usbfsen().set_bit()),
        }
    });
}


/// Wrapper around device-specific peripheral that provides unified register interface
pub struct UsbRegisters(USB);

impl core::ops::Deref for UsbRegisters {
    type Target = usb::RegisterBlock;

    fn deref(&self) -> &Self::Target {
        let ptr = USB::ptr() as *const Self::Target;
        unsafe { &*ptr }
    }
}

impl UsbRegisters {
    pub fn new(usb: USB) -> Self {
        Self(usb)
    }

    pub fn ep_register(index: u8) -> &'static usb::EPR {
        let usb_ptr = USB::ptr() as *const usb::RegisterBlock;
        unsafe { &(*usb_ptr).epr[index as usize] }
    }
}



pub trait UsbPins: Send { }

#[cfg(feature = "stm32f0")]
pub mod usb_pins {
    use super::hal::gpio::{Input, Floating};
    use super::hal::gpio::gpioa::{PA11, PA12};

    pub type UsbPinsType = (PA11<Input<Floating>>, PA12<Input<Floating>>);
    impl super::UsbPins for UsbPinsType {}
}

#[cfg(feature = "stm32f1")]
pub mod usb_pins {
    use super::hal::gpio::{Input, Floating};
    use super::hal::gpio::gpioa::{PA11, PA12};

    pub type UsbPinsType = (PA11<Input<Floating>>, PA12<Input<Floating>>);
    impl super::UsbPins for UsbPinsType {}
}

#[cfg(feature = "stm32f3")]
pub mod usb_pins {
    use super::hal::gpio::AF14;
    use super::hal::gpio::gpioa::{PA11, PA12};

    pub type UsbPinsType = (PA11<AF14>, PA12<AF14>);
    impl super::UsbPins for UsbPinsType {}
}

#[cfg(feature = "stm32l0")]
pub mod usb_pins {
    use super::hal::gpio::{Input, Floating};
    use super::hal::gpio::gpioa::{PA11, PA12};

    pub type UsbPinsType = (PA11<Input<Floating>>, PA12<Input<Floating>>);
    impl super::UsbPins for UsbPinsType {}
}

#[cfg(feature = "stm32l4")]
pub mod usb_pins {
    use super::hal::gpio::{AF10, Alternate, Input, Floating};
    use super::hal::gpio::gpioa::{PA11, PA12};

    pub type UsbPinsType = (
        PA11<Alternate<AF10, Input<Floating>>>,
        PA12<Alternate<AF10, Input<Floating>>>
    );
    impl super::UsbPins for UsbPinsType {}
}