Browse Source

Initial import, WIP.

Mathias Gottschlag 5 years ago
commit
398cb88d44
6 changed files with 430 additions and 0 deletions
  1. 3
    0
      .gitignore
  2. 13
    0
      Cargo.toml
  3. 1
    0
      rust-toolchain
  4. 388
    0
      src/bus.rs
  5. 1
    0
      src/endpoint.rs
  6. 24
    0
      src/lib.rs

+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
1
+/target
2
+Cargo.lock
3
+*.swp

+ 13
- 0
Cargo.toml View File

@@ -0,0 +1,13 @@
1
+[package]
2
+name = "mkl25z4-usbd"
3
+version = "0.1.0"
4
+authors = ["Mathias Gottschlag <mgottschlag@gmail.com>"]
5
+edition = "2018"
6
+
7
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8
+
9
+[dependencies]
10
+cortex-m = "0.6"
11
+mkl25z4 = { version = "0.0.3", features = ["rt"] }
12
+mkl25z4-hal = { git = "https://github.com/mgottschlag/mkl25z4-hal" }
13
+usb-device = "0.2.4"

+ 1
- 0
rust-toolchain View File

@@ -0,0 +1 @@
1
+nightly-2020-04-11

+ 388
- 0
src/bus.rs View File

@@ -0,0 +1,388 @@
1
+use core::mem::{self, MaybeUninit};
2
+use cortex_m::interrupt::{self, Mutex};
3
+use mkl25z4::{SIM, USB0};
4
+use usb_device::bus::{PollResult, UsbBusAllocator};
5
+use usb_device::endpoint::{EndpointAddress, EndpointType};
6
+use usb_device::{Result, UsbDirection, UsbError};
7
+
8
+use crate::UsbBuffers;
9
+
10
+pub const NUM_ENDPOINTS: usize = 16;
11
+pub const BUF_SIZE: usize = 64;
12
+
13
+#[repr(C)]
14
+pub(crate) struct BufferDescriptor {
15
+    flags: u32,
16
+    addr: u32,
17
+}
18
+
19
+impl BufferDescriptor {
20
+    // TODO
21
+}
22
+
23
+#[repr(align(512), C)]
24
+pub(crate) struct BufferDescriptorTable([BufferDescriptor; NUM_ENDPOINTS * 4]);
25
+
26
+impl BufferDescriptorTable {
27
+    pub(crate) fn new() -> Self {
28
+        Self([BufferDescriptor { flags: 0, addr: 0 }; NUM_ENDPOINTS * 4])
29
+    }
30
+}
31
+
32
+pub struct Endpoint {
33
+    ep_type: Option<EndpointType>,
34
+    in_buf: [[u8; BUF_SIZE]; 2],
35
+    out_buf: [[u8; BUF_SIZE]; 2],
36
+}
37
+
38
+impl Endpoint {
39
+    pub fn ep_type(&self) -> Option<EndpointType> {
40
+        self.ep_type
41
+    }
42
+
43
+    pub fn set_ep_type(&mut self, ep_type: EndpointType) {
44
+        self.ep_type = Some(ep_type);
45
+    }
46
+}
47
+
48
+impl Default for Endpoint {
49
+    fn default() -> Endpoint {
50
+        Endpoint {
51
+            ep_type: None,
52
+            in_buf: [[0; 64]; 2],
53
+            out_buf: [[0; 64]; 2],
54
+        }
55
+    }
56
+}
57
+pub struct UsbBus {
58
+    regs: Mutex<USB0>,
59
+    buffers: &'static mut UsbBuffers,
60
+    endpoints: [Endpoint; NUM_ENDPOINTS],
61
+    /*ep_allocator: EndpointMemoryAllocator<USB>,
62
+    max_endpoint: usize,*/
63
+}
64
+
65
+impl UsbBus {
66
+    /// Constructs a new USB peripheral driver.
67
+    pub fn new(
68
+        peripheral: USB0,
69
+        sim: &mut SIM,
70
+        buffers: &'static mut UsbBuffers,
71
+    ) -> UsbBusAllocator<Self> {
72
+        // TODO: Check whether the clocks are correct? USB requires a 48MHz reference clock.
73
+        // SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK;
74
+
75
+        // Enable the peripheral.
76
+        sim.scgc4.modify(|_, w| w.usbotg().set_bit());
77
+
78
+        let bus = UsbBus {
79
+            regs: Mutex::new(peripheral),
80
+            buffers: buffers,
81
+            /*ep_allocator: EndpointMemoryAllocator::new(),
82
+            max_endpoint: 0,*/
83
+            endpoints: [Endpoint::default(); NUM_ENDPOINTS],
84
+        };
85
+
86
+        UsbBusAllocator::new(bus)
87
+    }
88
+
89
+    /*pub fn free(self) -> USB0 {
90
+        // TODO: Disable the USB peripheral again?
91
+        // TODO: The following requires an updated bare-metal crate.
92
+        self.regs.into_inner()
93
+    }*/
94
+
95
+    /*/// Simulates a disconnect from the USB bus, causing the host to reset and re-enumerate the
96
+    /// device.
97
+    ///
98
+    /// Mostly used for development. By calling this at the start of your program ensures that the
99
+    /// host re-enumerates your device after a new program has been flashed.
100
+    ///
101
+    /// `disconnect` parameter is used to provide a custom disconnect function.
102
+    /// This function will be called with USB peripheral powered down
103
+    /// and interrupts disabled.
104
+    /// It should perform disconnect in a platform-specific way.
105
+    pub fn force_reenumeration<F: FnOnce()>(&self, disconnect: F) {
106
+        interrupt::free(|cs| {
107
+            let regs = self.regs.borrow(cs);
108
+
109
+            let pdwn = regs.cntr.read().pdwn().bit_is_set();
110
+            regs.cntr.modify(|_, w| w.pdwn().set_bit());
111
+
112
+            disconnect();
113
+
114
+            regs.cntr.modify(|_, w| w.pdwn().bit(pdwn));
115
+        });
116
+    }*/
117
+}
118
+
119
+impl usb_device::bus::UsbBus for UsbBus {
120
+    fn alloc_ep(
121
+        &mut self,
122
+        ep_dir: UsbDirection,
123
+        ep_addr: Option<EndpointAddress>,
124
+        ep_type: EndpointType,
125
+        max_packet_size: u16,
126
+        _interval: u8,
127
+    ) -> Result<EndpointAddress> {
128
+        for index in ep_addr
129
+            .map(|a| a.index()..a.index() + 1)
130
+            .unwrap_or(1..NUM_ENDPOINTS)
131
+        {
132
+            let ep = &mut self.endpoints[index];
133
+
134
+            match ep.ep_type() {
135
+                None => {
136
+                    ep.set_ep_type(ep_type);
137
+                }
138
+                Some(t) if t != ep_type => {
139
+                    continue;
140
+                }
141
+                _ => {}
142
+            };
143
+
144
+            match ep_dir {
145
+                UsbDirection::Out if !ep.is_out_buf_set() => {
146
+                    let (out_size, size_bits) = calculate_count_rx(max_packet_size as usize)?;
147
+
148
+                    let buffer = self.ep_allocator.allocate_buffer(out_size)?;
149
+
150
+                    ep.set_out_buf(buffer, size_bits);
151
+
152
+                    return Ok(EndpointAddress::from_parts(index, ep_dir));
153
+                }
154
+                UsbDirection::In if !ep.is_in_buf_set() => {
155
+                    let size = (max_packet_size as usize + 1) & !0x01;
156
+
157
+                    let buffer = self.ep_allocator.allocate_buffer(size)?;
158
+
159
+                    ep.set_in_buf(buffer);
160
+
161
+                    return Ok(EndpointAddress::from_parts(index, ep_dir));
162
+                }
163
+                _ => {}
164
+            }
165
+        }
166
+
167
+        Err(match ep_addr {
168
+            Some(_) => UsbError::InvalidEndpoint,
169
+            None => UsbError::EndpointOverflow,
170
+        })
171
+    }
172
+
173
+    fn enable(&mut self) {
174
+        /*let mut max = 0;
175
+        for (index, ep) in self.endpoints.iter().enumerate() {
176
+            if ep.is_out_buf_set() || ep.is_in_buf_set() {
177
+                max = index;
178
+            }
179
+        }
180
+
181
+        self.max_endpoint = max;*/
182
+
183
+        interrupt::free(|cs| {
184
+            let regs = self.regs.borrow(cs);
185
+
186
+            // Reset the USB module.
187
+            regs.usbtrc0.modify(|_, w| w.usbreset().set_bit());
188
+            // TODO: Wait two USB clock cycles for reset.
189
+
190
+            // Set the BDT base registers.
191
+            let bdt_address = &self.buffers.bdt as *const _ as u32;
192
+            regs.bdtpage1
193
+                .modify(|_, w| w.bdtba().bits((bdt_address >> 8) as u8));
194
+            regs.bdtpage2
195
+                .modify(|_, w| w.bdtba().bits((bdt_address >> 16) as u8));
196
+            regs.bdtpage3
197
+                .modify(|_, w| w.bdtba().bits((bdt_address >> 24) as u8));
198
+
199
+            // Clear all interrupt flags.
200
+            regs.istat.write(|w| unsafe { w.bits(0xff) });
201
+            regs.otgistat.write(|w| unsafe { w.bits(0xff) });
202
+            // Clear all errors.
203
+            regs.errstat.write(|w| unsafe { w.bits(0xff) });
204
+            // Undocumented interrupt bit?
205
+            regs.usbtrc0.write(|w| unsafe { w.bits(0x40) });
206
+
207
+            // Enable USB.
208
+            regs.ctl.write(|w| w.usbensofen().set_bit());
209
+            // Disable suspend, enable weak pull down.
210
+            regs.usbctrl.write(|w| w.pde().set_bit());
211
+            // Enable USB reset interrupt.
212
+            regs.inten.modify(|_, w| w.usbrsten().set_bit());
213
+        });
214
+    }
215
+
216
+    fn reset(&self) {
217
+        interrupt::free(|cs| {
218
+            let regs = self.regs.borrow(cs);
219
+
220
+            regs.ctl.modify(|_, w| w.oddrst().set_bit());
221
+
222
+            // Initialize all buffer descriptors and endpoints.
223
+            for ep in self.endpoints.iter() {
224
+                ep.configure(cs);
225
+            }
226
+
227
+            // Clear all interrupts.
228
+            regs.istat.write(|w| unsafe { w.bits(0xff) });
229
+            regs.errstat.write(|w| unsafe { w.bits(0xff) });
230
+
231
+            // After reset, the address is 0.
232
+            regs.addr.modify(|_, w| w.addr().bits(0));
233
+            // Enable all relevant interrupts.
234
+            regs.erren.modify(|_, w| unsafe { w.bits(0xff) });
235
+            regs.inten.modify(|_, w| {
236
+                w.usbrsten()
237
+                    .set_bit()
238
+                    .erroren()
239
+                    .set_bit()
240
+                    .softoken()
241
+                    .set_bit()
242
+                    .tokdneen()
243
+                    .set_bit()
244
+                    .sleepen()
245
+                    .set_bit()
246
+                    .stallen()
247
+                    .set_bit()
248
+            });
249
+        });
250
+    }
251
+
252
+    fn set_device_address(&self, addr: u8) {
253
+        interrupt::free(|cs| {
254
+            self.regs
255
+                .borrow(cs)
256
+                .addr
257
+                .modify(|_, w| w.addr().bits(addr as u8));
258
+        });
259
+    }
260
+
261
+    fn poll(&self) -> PollResult {
262
+        interrupt::free(|cs| {
263
+            let regs = self.regs.borrow(cs);
264
+
265
+            let istat = regs.istat.read();
266
+
267
+            if istr.wkup().bit_is_set() {
268
+                // Interrupt flag bits are write-0-to-clear, other bits should be written as 1 to avoid
269
+                // race conditions
270
+                regs.istr
271
+                    .write(|w| unsafe { w.bits(0xffff) }.wkup().clear_bit());
272
+
273
+                // Required by datasheet
274
+                regs.cntr.modify(|_, w| w.fsusp().clear_bit());
275
+
276
+                PollResult::Resume
277
+            } else if istr.reset().bit_is_set() {
278
+                regs.istr
279
+                    .write(|w| unsafe { w.bits(0xffff) }.reset().clear_bit());
280
+
281
+                PollResult::Reset
282
+            } else if istr.susp().bit_is_set() {
283
+                regs.istr
284
+                    .write(|w| unsafe { w.bits(0xffff) }.susp().clear_bit());
285
+
286
+                PollResult::Suspend
287
+            } else if istr.ctr().bit_is_set() {
288
+                let mut ep_out = 0;
289
+                let mut ep_in_complete = 0;
290
+                let mut ep_setup = 0;
291
+                let mut bit = 1;
292
+
293
+                for ep in &self.endpoints[0..=self.max_endpoint] {
294
+                    let v = ep.read_reg();
295
+
296
+                    if v.ctr_rx().bit_is_set() {
297
+                        ep_out |= bit;
298
+
299
+                        if v.setup().bit_is_set() {
300
+                            ep_setup |= bit;
301
+                        }
302
+                    }
303
+
304
+                    if v.ctr_tx().bit_is_set() {
305
+                        ep_in_complete |= bit;
306
+
307
+                        interrupt::free(|cs| {
308
+                            ep.clear_ctr_tx(cs);
309
+                        });
310
+                    }
311
+
312
+                    bit <<= 1;
313
+                }
314
+
315
+                PollResult::Data {
316
+                    ep_out,
317
+                    ep_in_complete,
318
+                    ep_setup,
319
+                }
320
+            } else {
321
+                PollResult::None
322
+            }
323
+        })
324
+    }
325
+
326
+    fn write(&self, ep_addr: EndpointAddress, buf: &[u8]) -> Result<usize> {
327
+        if !ep_addr.is_in() {
328
+            return Err(UsbError::InvalidEndpoint);
329
+        }
330
+
331
+        self.endpoints[ep_addr.index()].write(buf)
332
+    }
333
+
334
+    fn read(&self, ep_addr: EndpointAddress, buf: &mut [u8]) -> Result<usize> {
335
+        if !ep_addr.is_out() {
336
+            return Err(UsbError::InvalidEndpoint);
337
+        }
338
+
339
+        self.endpoints[ep_addr.index()].read(buf)
340
+    }
341
+
342
+    fn set_stalled(&self, ep_addr: EndpointAddress, stalled: bool) {
343
+        interrupt::free(|cs| {
344
+            if self.is_stalled(ep_addr) == stalled {
345
+                return;
346
+            }
347
+
348
+            let ep = &self.endpoints[ep_addr.index()];
349
+
350
+            match (stalled, ep_addr.direction()) {
351
+                (true, UsbDirection::In) => ep.set_stat_tx(cs, EndpointStatus::Stall),
352
+                (true, UsbDirection::Out) => ep.set_stat_rx(cs, EndpointStatus::Stall),
353
+                (false, UsbDirection::In) => ep.set_stat_tx(cs, EndpointStatus::Nak),
354
+                (false, UsbDirection::Out) => ep.set_stat_rx(cs, EndpointStatus::Valid),
355
+            };
356
+        });
357
+    }
358
+
359
+    fn is_stalled(&self, ep_addr: EndpointAddress) -> bool {
360
+        let ep = &self.endpoints[ep_addr.index()];
361
+        let reg_v = ep.read_reg();
362
+
363
+        let status = match ep_addr.direction() {
364
+            UsbDirection::In => reg_v.stat_tx().bits(),
365
+            UsbDirection::Out => reg_v.stat_rx().bits(),
366
+        };
367
+
368
+        status == (EndpointStatus::Stall as u8)
369
+    }
370
+
371
+    fn suspend(&self) {
372
+        interrupt::free(|cs| {
373
+            self.regs
374
+                .borrow(cs)
375
+                .cntr
376
+                .modify(|_, w| w.fsusp().set_bit().lpmode().set_bit());
377
+        });
378
+    }
379
+
380
+    fn resume(&self) {
381
+        interrupt::free(|cs| {
382
+            self.regs
383
+                .borrow(cs)
384
+                .cntr
385
+                .modify(|_, w| w.fsusp().clear_bit().lpmode().clear_bit());
386
+        });
387
+    }
388
+}

+ 1
- 0
src/endpoint.rs View File

@@ -0,0 +1 @@
1
+

+ 24
- 0
src/lib.rs View File

@@ -0,0 +1,24 @@
1
+//! USB peripheral driver for MKL25Z microcontrollers.
2
+
3
+#![no_std]
4
+
5
+pub mod bus;
6
+//mod endpoint;
7
+//mod endpoint_memory;
8
+//mod registers;
9
+pub use crate::bus::UsbBus;
10
+
11
+//mod pac;
12
+
13
+pub struct UsbBuffers {
14
+    bdt: bus::BufferDescriptorTable,
15
+    // TODO
16
+}
17
+
18
+impl UsbBuffers {
19
+    const fn new() -> UsbBuffers {
20
+        UsbBuffers {
21
+            bdt: bus::BufferDescriptorTable::new(),
22
+        }
23
+    }
24
+}

Loading…
Cancel
Save