atsamd_usb_host/
lib.rs

1//! USB Host driver implementation for SAMD* series chips.
2
3#![no_std]
4mod pipe;
5
6use pipe::{PipeErr, PipeTable};
7
8use usb_host::{
9    DescriptorType, DeviceDescriptor, Direction, Driver, DriverError, Endpoint, RequestCode,
10    RequestDirection, RequestKind, RequestRecipient, RequestType, TransferError, TransferType,
11    USBHost, WValue,
12};
13
14use atsamd_hal::{
15    calibration::{usb_transn_cal, usb_transp_cal, usb_trim_cal},
16    clock::{ClockGenId, ClockSource, GenericClockController},
17    gpio::{self, Floating, Input, OpenDrain, Output},
18    target_device::{PM, USB},
19};
20use embedded_hal::digital::v2::OutputPin;
21use log::{debug, error, info, trace, warn};
22use starb::{Reader, RingBuffer, Writer};
23
24#[derive(Clone, Copy, Debug, PartialEq)]
25pub enum Event {
26    Error,
27    Detached,
28    Attached,
29}
30type Events = RingBuffer<Event>;
31type EventReader = Reader<'static, Event>;
32type EventWriter = Writer<'static, Event>;
33
34const NAK_LIMIT: usize = 15;
35
36// Ring buffer for sharing events from interrupt context.
37static mut EVENTS: Events = Events::new();
38
39#[derive(Clone, Copy, Debug, PartialEq)]
40enum DetachedState {
41    Initialize,
42    WaitForDevice,
43    Illegal,
44}
45
46#[derive(Clone, Copy, Debug, PartialEq)]
47enum AttachedState {
48    ResetBus,
49    WaitResetComplete,
50    WaitSOF(usize),
51}
52
53#[derive(Clone, Copy, Debug, PartialEq)]
54enum SteadyState {
55    Configuring,
56    Running,
57    ErrorUntil(usize),
58}
59
60#[derive(Clone, Copy, Debug, PartialEq)]
61enum TaskState {
62    Detached(DetachedState),
63    Attached(AttachedState),
64    Steady(SteadyState),
65}
66
67use core::mem::{self, MaybeUninit};
68use core::ptr;
69
70/// How long to wait after a permanent error before resetting the
71/// host.
72const ERROR_RESET_DELAY: usize = 200;
73
74const MAX_DEVICES: usize = 4;
75struct DeviceTable {
76    tbl: [Option<Device>; MAX_DEVICES],
77}
78impl DeviceTable {
79    fn new() -> Self {
80        let tbl = {
81            let mut devs: [MaybeUninit<Option<Device>>; MAX_DEVICES] =
82                unsafe { MaybeUninit::uninit().assume_init() };
83            for d in &mut devs[..] {
84                unsafe { ptr::write(d.as_mut_ptr(), None) }
85            }
86            unsafe { mem::transmute(devs) }
87        };
88
89        Self { tbl }
90    }
91
92    /// Allocate a device with the next available address.
93    // TODO: get rid of the millis argument somehow, but the device
94    // does need a way of tracking time for Settle reasons.
95    fn next(&mut self) -> Option<&mut Device> {
96        for i in 1..self.tbl.len() {
97            if self.tbl[i].is_none() {
98                let d = Device { addr: i as u8 };
99                self.tbl[i] = Some(d);
100                return self.tbl[i].as_mut();
101            }
102        }
103        None
104    }
105
106    /// Remove the device at address `addr`.
107    fn remove(&mut self, addr: u8) -> Option<Device> {
108        core::mem::replace(&mut self.tbl[addr as usize], None)
109    }
110}
111
112struct Device {
113    addr: u8,
114}
115
116pub struct SAMDHost<'a, F> {
117    usb: USB,
118
119    events: EventReader,
120    task_state: TaskState,
121
122    // Need chunk of RAM for USB pipes, which gets used with DESCADD
123    // register.
124    pipe_table: PipeTable,
125
126    devices: DeviceTable,
127
128    _dm_pad: gpio::Pa24<gpio::PfG>,
129    _dp_pad: gpio::Pa25<gpio::PfG>,
130    _sof_pad: Option<gpio::Pa23<gpio::PfG>>,
131    host_enable_pin: Option<gpio::Pa28<Output<OpenDrain>>>,
132
133    // To get current milliseconds.
134    millis: &'a F,
135}
136
137pub struct Pins {
138    dm_pin: gpio::Pa24<Input<Floating>>,
139    dp_pin: gpio::Pa25<Input<Floating>>,
140    sof_pin: Option<gpio::Pa23<Input<Floating>>>,
141    host_enable_pin: Option<gpio::Pa28<Input<Floating>>>,
142}
143impl Pins {
144    pub fn new(
145        dm_pin: gpio::Pa24<Input<Floating>>,
146        dp_pin: gpio::Pa25<Input<Floating>>,
147        sof_pin: Option<gpio::Pa23<Input<Floating>>>,
148        host_enable_pin: Option<gpio::Pa28<Input<Floating>>>,
149    ) -> Self {
150        Self {
151            dm_pin,
152            dp_pin,
153            sof_pin,
154            host_enable_pin,
155        }
156    }
157}
158
159impl<'a, F> SAMDHost<'a, F>
160where
161    F: Fn() -> usize,
162{
163    pub fn new(
164        usb: USB,
165        pins: Pins,
166        port: &mut gpio::Port,
167        clocks: &mut GenericClockController,
168        pm: &mut PM,
169        millis: &'a F,
170    ) -> (Self, impl FnMut()) {
171        let (eventr, mut eventw) = unsafe { EVENTS.split() };
172
173        let rc = Self {
174            usb,
175
176            events: eventr,
177            task_state: TaskState::Detached(DetachedState::Initialize),
178
179            pipe_table: PipeTable::new(),
180
181            devices: DeviceTable::new(),
182
183            _dm_pad: pins.dm_pin.into_function_g(port),
184            _dp_pad: pins.dp_pin.into_function_g(port),
185            _sof_pad: pins.sof_pin.map(|p| p.into_function_g(port)),
186            host_enable_pin: pins.host_enable_pin.map(|p| p.into_open_drain_output(port)),
187
188            millis,
189        };
190
191        pm.apbbmask.modify(|_, w| w.usb_().set_bit());
192
193        // Set up USB clock from 48MHz source on generic clock 6.
194        clocks.configure_gclk_divider_and_source(ClockGenId::GCLK6, 1, ClockSource::DFLL48M, false);
195        let gclk6 = clocks
196            .get_gclk(ClockGenId::GCLK6)
197            .expect("Could not get clock 6");
198        clocks.usb(&gclk6);
199
200        let usbp = &rc.usb as *const _ as usize;
201        (rc, move || handler(usbp, &mut eventw))
202    }
203
204    pub fn reset_periph(&mut self) {
205        debug!("resetting usb");
206        // Reset the USB peripheral and wait for sync.
207        self.usb.host().ctrla.write(|w| w.swrst().set_bit());
208        while self.usb.host().syncbusy.read().swrst().bit_is_set() {}
209
210        // Specify host mode.
211        self.usb.host().ctrla.modify(|_, w| w.mode().host());
212
213        // Unsafe due to use of raw bits method.
214        unsafe {
215            self.usb.host().padcal.write(|w| {
216                w.transn().bits(usb_transn_cal());
217                w.transp().bits(usb_transp_cal());
218                w.trim().bits(usb_trim_cal())
219            });
220        }
221
222        // Use normal, which is 0 and apparently means low-and-full capable
223        self.usb.host().ctrlb.modify(|_, w| w.spdconf().normal());
224        // According to docs, 1,2,3 are reserved, but .fs returns 3
225        //self.usb.host().ctrlb.modify(|_, w| w.spdconf().fs());
226
227        self.usb.host().ctrla.modify(|_, w| w.runstdby().set_bit()); // keep usb clock running in standby.
228
229        // Set address of USB SRAM.
230        // Unsafe due to use of raw bits method.
231        unsafe {
232            self.usb
233                .host()
234                .descadd
235                .write(|w| w.bits(&self.pipe_table as *const _ as u32));
236        }
237
238        if let Some(he_pin) = &mut self.host_enable_pin {
239            he_pin.set_high().expect("turning on usb host enable pin");
240        }
241
242        self.usb.host().intenset.write(|w| {
243            w.dconn().set_bit();
244            w.ddisc().set_bit()
245        });
246
247        self.usb.host().ctrla.modify(|_, w| w.enable().set_bit());
248        while self.usb.host().syncbusy.read().enable().bit_is_set() {}
249
250        // Set VBUS OK to allow host operation.
251        self.usb.host().ctrlb.modify(|_, w| w.vbusok().set_bit());
252        debug!("...done");
253    }
254
255    pub fn task(&mut self, drivers: &mut [&mut dyn Driver]) {
256        static mut LAST_TASK_STATE: TaskState = TaskState::Detached(DetachedState::Illegal);
257
258        if let Some(event) = self.events.shift() {
259            trace!("Found event: {:?}", event);
260            self.task_state = match event {
261                Event::Error => TaskState::Detached(DetachedState::Illegal),
262                Event::Detached => {
263                    if let TaskState::Detached(_) = self.task_state {
264                        self.task_state
265                    } else {
266                        TaskState::Detached(DetachedState::Initialize)
267                    }
268                }
269                Event::Attached => {
270                    if let TaskState::Detached(_) = self.task_state {
271                        TaskState::Attached(AttachedState::ResetBus)
272                    } else {
273                        self.task_state
274                    }
275                }
276            };
277        }
278
279        static mut LAST_CBITS: u16 = 0;
280        static mut LAST_FLAGS: u16 = 0;
281        let cbits = self.usb.host().ctrlb.read().bits();
282        let bits = self.usb.host().intflag.read().bits();
283        unsafe {
284            if LAST_CBITS != cbits || LAST_FLAGS != bits || LAST_TASK_STATE != self.task_state {
285                trace!(
286                    "cb: {:x}, f: {:x} changing state {:?} -> {:?}",
287                    cbits,
288                    bits,
289                    LAST_TASK_STATE,
290                    self.task_state,
291                );
292            }
293            LAST_CBITS = cbits;
294            LAST_FLAGS = bits;
295            LAST_TASK_STATE = self.task_state
296        };
297
298        self.fsm(drivers);
299    }
300
301    fn fsm(&mut self, drivers: &mut [&mut dyn Driver]) {
302        // respond to events from interrupt.
303        match self.task_state {
304            TaskState::Detached(s) => self.detached_fsm(s),
305            TaskState::Attached(s) => self.attached_fsm(s),
306            TaskState::Steady(s) => self.steady_fsm(s, drivers),
307        };
308    }
309
310    fn detached_fsm(&mut self, s: DetachedState) {
311        match s {
312            DetachedState::Initialize => {
313                self.reset_periph();
314                // TODO: Free resources.
315
316                self.task_state = TaskState::Detached(DetachedState::WaitForDevice);
317            }
318
319            // Do nothing state. Just wait for an interrupt to come in
320            // saying we have a device attached.
321            DetachedState::WaitForDevice => {}
322
323            // TODO: should probably reset everything if we end up here somehow.
324            DetachedState::Illegal => {}
325        }
326    }
327
328    fn attached_fsm(&mut self, s: AttachedState) {
329        match s {
330            AttachedState::ResetBus => {
331                self.usb.host().ctrlb.modify(|_, w| w.busreset().set_bit());
332                self.task_state = TaskState::Attached(AttachedState::WaitResetComplete);
333            }
334
335            AttachedState::WaitResetComplete => {
336                if self.usb.host().intflag.read().rst().bit_is_set() {
337                    trace!("reset was sent");
338                    self.usb.host().intflag.write(|w| w.rst().set_bit());
339
340                    // Seems unneccesary, since SOFE will be set
341                    // immediately after reset according to ยง32.6.3.3.
342                    self.usb.host().ctrlb.modify(|_, w| w.sofe().set_bit());
343                    // USB spec requires 20ms of SOF after bus reset.
344                    self.task_state =
345                        TaskState::Attached(AttachedState::WaitSOF((self.millis)() + 20));
346                }
347            }
348
349            AttachedState::WaitSOF(until) => {
350                if self.usb.host().intflag.read().hsof().bit_is_set() {
351                    self.usb.host().intflag.write(|w| w.hsof().set_bit());
352                    if (self.millis)() >= until {
353                        self.task_state = TaskState::Steady(SteadyState::Configuring);
354                    }
355                }
356            }
357        }
358    }
359
360    fn steady_fsm(&mut self, s: SteadyState, drivers: &mut [&mut dyn Driver]) {
361        match s {
362            SteadyState::Configuring => {
363                self.task_state = match self.configure_dev(drivers) {
364                    Ok(_) => TaskState::Steady(SteadyState::Running),
365                    Err(e) => {
366                        warn!("Enumeration error: {:?}", e);
367                        TaskState::Steady(SteadyState::ErrorUntil(
368                            (self.millis)() + ERROR_RESET_DELAY,
369                        ))
370                    }
371                }
372            }
373
374            SteadyState::Running => {
375                for d in &mut drivers[..] {
376                    if let Err(e) = d.tick((self.millis)(), self) {
377                        warn!("running driver {:?}: {:?}", d, e);
378                        if let DriverError::Permanent(a, _) = e {
379                            d.remove_device(a);
380                            self.devices.remove(a);
381                            self.task_state = TaskState::Steady(SteadyState::ErrorUntil(
382                                (self.millis)() + ERROR_RESET_DELAY,
383                            ))
384                        }
385                    }
386                }
387            }
388
389            // TODO: this is too heavy-handed: resetting the whole
390            // device when only one may be a problem.
391            SteadyState::ErrorUntil(when) => {
392                if (self.millis)() >= when {
393                    self.task_state = TaskState::Detached(DetachedState::Initialize);
394                }
395            }
396        }
397    }
398
399    fn configure_dev(&mut self, drivers: &mut [&mut dyn Driver]) -> Result<(), TransferError> {
400        let none: Option<&mut [u8]> = None;
401        let max_packet_size: u16 = match self.usb.host().status.read().speed().bits() {
402            0x0 => 64,
403            _ => 8,
404        };
405        let mut a0ep0 = Addr0EP0 {
406            max_packet_size,
407            in_toggle: true,
408            out_toggle: true,
409        };
410
411        let mut dev_desc: MaybeUninit<DeviceDescriptor> = MaybeUninit::uninit();
412        let len = self.control_transfer(
413            &mut a0ep0,
414            RequestType::from((
415                RequestDirection::DeviceToHost,
416                RequestKind::Standard,
417                RequestRecipient::Device,
418            )),
419            RequestCode::GetDescriptor,
420            WValue::from((0, DescriptorType::Device as u8)),
421            0,
422            Some(unsafe { to_slice_mut(&mut dev_desc) }),
423        )?;
424        assert!(len == mem::size_of::<DeviceDescriptor>());
425        let dev_desc = unsafe { dev_desc.assume_init() };
426
427        trace!(" -- dev_desc: {:?}", dev_desc);
428
429        // TODO: new error for being out of devices.
430        let addr = self
431            .devices
432            .next()
433            .ok_or(TransferError::Permanent("out of devices"))?
434            .addr;
435        debug!("Setting address to {}.", addr);
436        self.control_transfer(
437            &mut a0ep0,
438            RequestType::from((
439                RequestDirection::HostToDevice,
440                RequestKind::Standard,
441                RequestRecipient::Device,
442            )),
443            RequestCode::SetAddress,
444            WValue::from((addr, 0)),
445            0,
446            none,
447        )?;
448
449        // Now that the device is addressed, see if any drivers want
450        // it.
451        for d in &mut drivers[..] {
452            if d.want_device(&dev_desc) {
453                info!("{:?} will take address {}.", d, addr);
454                let res = d.add_device(dev_desc, addr);
455                match res {
456                    Ok(_) => return Ok(()),
457                    Err(_) => return Err(TransferError::Permanent("out of addresses")),
458                }
459            }
460        }
461        Ok(())
462    }
463}
464
465struct Addr0EP0 {
466    max_packet_size: u16,
467    in_toggle: bool,
468    out_toggle: bool,
469}
470impl Endpoint for Addr0EP0 {
471    fn address(&self) -> u8 {
472        0
473    }
474
475    fn endpoint_num(&self) -> u8 {
476        0
477    }
478
479    fn transfer_type(&self) -> TransferType {
480        TransferType::Control
481    }
482
483    fn direction(&self) -> Direction {
484        Direction::In
485    }
486
487    fn max_packet_size(&self) -> u16 {
488        self.max_packet_size
489    }
490
491    fn in_toggle(&self) -> bool {
492        self.in_toggle
493    }
494
495    fn set_in_toggle(&mut self, toggle: bool) {
496        self.in_toggle = toggle;
497    }
498
499    fn out_toggle(&self) -> bool {
500        self.out_toggle
501    }
502
503    fn set_out_toggle(&mut self, toggle: bool) {
504        self.out_toggle = toggle;
505    }
506}
507
508pub fn handler(usbp: usize, events: &mut EventWriter) {
509    let usb: &mut USB = unsafe { core::mem::transmute(usbp) };
510    let flags = usb.host().intflag.read();
511
512    trace!("USB - {:x}", flags.bits());
513
514    let mut unshift_event = |e: Event| {
515        if let Err(e) = events.unshift(e) {
516            error!("Couldn't write USB event to queue: {:?}", e);
517        }
518    };
519
520    if flags.dconn().bit_is_set() {
521        trace!(" +dconn");
522        usb.host().intflag.write(|w| w.dconn().set_bit());
523        unshift_event(Event::Attached);
524    }
525
526    if flags.ddisc().bit_is_set() {
527        trace!(" +ddisc");
528        usb.host().intflag.write(|w| w.ddisc().set_bit());
529        unshift_event(Event::Detached);
530    }
531}
532
533impl From<PipeErr> for TransferError {
534    fn from(v: PipeErr) -> Self {
535        match v {
536            PipeErr::TransferFail => Self::Retry("transfer failed"),
537            PipeErr::Flow => Self::Retry("data flow"),
538            PipeErr::DataToggle => Self::Retry("toggle sequence"),
539            PipeErr::ShortPacket => Self::Permanent("short packet"),
540            PipeErr::InvalidPipe => Self::Permanent("invalid pipe"),
541            PipeErr::InvalidToken => Self::Permanent("invalid token"),
542            PipeErr::Stall => Self::Permanent("stall"),
543            PipeErr::PipeErr => Self::Permanent("pipe error"),
544            PipeErr::HWTimeout => Self::Permanent("hardware timeout"),
545            PipeErr::SWTimeout => Self::Permanent("software timeout"),
546            PipeErr::PID => Self::Permanent("pid error"),
547            PipeErr::DataPID => Self::Permanent("data pid error"),
548            PipeErr::CRC16 => Self::Permanent("crc16 error"),
549            //PipeErr::Other(s) => Self::Permanent(s),
550        }
551    }
552}
553
554impl<F> USBHost for SAMDHost<'_, F>
555where
556    F: Fn() -> usize,
557{
558    fn control_transfer(
559        &mut self,
560        ep: &mut dyn Endpoint,
561        bm_request_type: RequestType,
562        b_request: RequestCode,
563        w_value: WValue,
564        w_index: u16,
565        buf: Option<&mut [u8]>,
566    ) -> Result<usize, TransferError> {
567        let mut pipe = self.pipe_table.pipe_for(self.usb.host_mut(), ep);
568        let len = pipe.control_transfer(
569            ep,
570            bm_request_type,
571            b_request,
572            w_value,
573            w_index,
574            buf,
575            self.millis,
576        )?;
577        Ok(len)
578    }
579
580    fn in_transfer(
581        &mut self,
582        ep: &mut dyn Endpoint,
583        buf: &mut [u8],
584    ) -> Result<usize, TransferError> {
585        let mut pipe = self.pipe_table.pipe_for(self.usb.host_mut(), ep);
586        let len = pipe.in_transfer(ep, buf, NAK_LIMIT, self.millis)?;
587        Ok(len)
588    }
589
590    fn out_transfer(&mut self, ep: &mut dyn Endpoint, buf: &[u8]) -> Result<usize, TransferError> {
591        let mut pipe = self.pipe_table.pipe_for(self.usb.host_mut(), ep);
592        let len = pipe.out_transfer(ep, buf, NAK_LIMIT, self.millis)?;
593        Ok(len)
594    }
595}
596
597unsafe fn to_slice_mut<T>(v: &mut T) -> &mut [u8] {
598    let ptr = v as *mut T as *mut u8;
599    let len = mem::size_of::<T>();
600    core::slice::from_raw_parts_mut(ptr, len)
601}