Numworks Epsilon  1.4.1
Graphing Calculator Operating System
usb.cpp
Go to the documentation of this file.
1 #include <ion/usb.h>
2 #include "usb.h"
3 #include <ion/display.h>
4 #include "device.h"
5 #include "display.h"
6 #include "regs/regs.h"
7 #include <stdlib.h>
8 
9 namespace Ion {
10 namespace USB {
11 
12 bool isPlugged() {
13  return Device::VbusPin.group().IDR()->get(Device::VbusPin.pin());
14 }
15 
16 bool isEnumerated() {
17  /* Note: This implementation is not perfect. One would assume isEnumerated to
18  * return true for as long as the device is enumerated. But the GINTSTS
19  * register will be cleared in the poll() routine. */
20  return OTG.GINTSTS()->getENUMDNE();
21 }
22 
24  OTG.GINTSTS()->setENUMDNE(true);
25 }
26 
27 void enable() {
28  // Get out of soft-disconnected state
29  OTG.DCTL()->setSDIS(false);
30 }
31 
32 void disable() {
33  // Get into soft-disconnected state
34  OTG.DCTL()->setSDIS(true);
35 }
36 
37 }
38 }
39 
40 namespace Ion {
41 namespace USB {
42 namespace Device {
43 
44 void init() {
45  initGPIO();
46  initOTG();
47 }
48 
49 void shutdown() {
50  shutdownOTG();
51  shutdownGPIO();
52 }
53 
54 static inline void DEBUGTOGGLE() {
55  bool state = GPIOC.ODR()->get(11);
56  GPIOC.ODR()->set(11, !state);
57 }
58 
59 #include <stdlib.h>
60 
61 void initGPIO() {
62 
63  // DEBUG GPIO pin
65  GPIOC.ODR()->set(11, false);
66 
67  /* Configure the GPIO
68  * The VBUS pin is connected to the USB VBUS port. To read if the USB is
69  * plugged, the pin must be pulled down. */
70  // FIXME: Understand how the Vbus pin really works!
71 #if 0
72  VbusPin.group().MODER()->setMode(VbusPin.pin(), GPIO::MODER::Mode::Input);
73  VbusPin.group().PUPDR()->setPull(VbusPin.pin(), GPIO::PUPDR::Pull::Down);
74 #else
75  VbusPin.group().MODER()->setMode(VbusPin.pin(), GPIO::MODER::Mode::AlternateFunction);
76  VbusPin.group().AFR()->setAlternateFunction(VbusPin.pin(), GPIO::AFR::AlternateFunction::AF10);
77 #endif
78 
79  DmPin.group().MODER()->setMode(DmPin.pin(), GPIO::MODER::Mode::AlternateFunction);
80  DmPin.group().AFR()->setAlternateFunction(DmPin.pin(), GPIO::AFR::AlternateFunction::AF10);
81 
82  DpPin.group().MODER()->setMode(DpPin.pin(), GPIO::MODER::Mode::AlternateFunction);
83  DpPin.group().AFR()->setAlternateFunction(DpPin.pin(), GPIO::AFR::AlternateFunction::AF10);
84 }
85 
86 void shutdownGPIO() {
87  constexpr static GPIOPin USBPins[] = {DpPin, DmPin, VbusPin};
88  for (const GPIOPin & g : USBPins) {
90  g.group().PUPDR()->setPull(g.pin(), GPIO::PUPDR::Pull::None);
91  }
92 }
93 
94 void initOTG() {
95  // Wait for AHB idle
96  while (!OTG.GRSTCTL()->getAHBIDL()) {
97  }
98 
99  /* Core soft reset: Clears the interrupts and many of the CSR register bits,
100  * resets state machines, flushes the FIFOs and terminates USB transactions.*/
101  OTG.GRSTCTL()->setCSRST(true);
102  while (OTG.GRSTCTL()->getCSRST()) {
103  }
104 
105  /* Enable the transceiver module of the PHY. It must be done to allow any USB
106  * operation */
107  OTG.GCCFG()->setPWRDWN(true);
108 
109  /* Enable VBUS sensing comparators to detect valid levels for USB operation.
110  * This is used for instance to end the session if the host is switched off.*/
111  OTG.GCCFG()->setVBDEN(true);
112 
113  // Force peripheral only mode
114  OTG.GUSBCFG()->setFDMOD(true);
115 
116  // Configure the USB turnaround time, depending on the AHB clock speed (96MHz)
117  OTG.GUSBCFG()->setTRDT(0x6);
118 
119  // Clear the interrupts
120  OTG.GINTSTS()->set(0);
121 
122  // Full speed device
124 
125  /* RxFIFO size. The value is in terms of 32-bit words.
126  * According to the reference manual, it should be, at minimum:
127  * (4 * number of control endpoints + 6)
128  * To receive SETUP packets on control endpoint
129  * + ((largest USB packet used / 4) + 1)
130  * To receive 1 USB packet + 1 packet status
131  * + (2 * number of OUT endpoints)
132  * Transfer complete status information
133  * + 1 for Global NAK
134  * So, for the calculator: (4*1+6) + (64/4 + 1) + (2*1) + 1 = 30
135  * As the RAM size is 1.25kB, the size should be at most 320, minus the space
136  * for the Tx FIFOs.
137  * However, we tested and found that only values between 40 and 255 actually
138  * work. We arbitrarily chose 128. */
139  OTG.GRXFSIZ()->setRXFD(128);
140 
141  // Unmask the interrupt line assertions
142  OTG.GAHBCFG()->setGINTMSK(true);
143 
144  // Restart the PHY clock
145  OTG.PCGCCTL()->setSTPPCLK(false);
146 
147  // Pick which interrupts we're interested in
148  class OTG::GINTMSK intMask(0); // Reset value
149  intMask.setENUMDNEM(true); // Speed enumeration done
150  intMask.setRXFLVLM(true); // Receive FIFO non empty
151  intMask.setIEPINT(true); // IN endpoint interrupt
152  OTG.GINTMSK()->set(intMask);
153 
154  // Unmask IN interrupts for endpoint 0 only
155  OTG.DAINTMSK()->setIEPM(1);
156 
157  /* Unmask the IN transfer completed interrupt for all endpoints. This
158  * interrupt warns that a IN transaction happened on the endpoint. */
159  OTG.DIEPMSK()->setXFRCM(true);
160 
161  /* To communicate with a USB host, the device still needs to get out of soft-
162  * disconnected state (SDIS in the DCTL register). We do this when we detect
163  * that the USB cable is plugged. */
164 }
165 
166 void shutdownOTG() {
167  // Core soft reset
168  OTG.GRSTCTL()->setCSRST(true);
169  while (OTG.GRSTCTL()->getCSRST()) {
170  }
171 
172  // Get into soft-disconnected state
173  OTG.DCTL()->setSDIS(true);
174 
175  // Stop the PHY clock
176  OTG.PCGCCTL()->setSTPPCLK(true);
177 
178  // Stop VBUS sensing
179  OTG.GCCFG()->setVBDEN(false);
180 
181  // Disable the transceiver module of the PHY
182  OTG.GCCFG()->setPWRDWN(false);
183 }
184 
185 }
186 }
187 }
bool isPlugged()
Definition: usb.cpp:12
void shutdownOTG()
Definition: usb.cpp:166
void init()
Definition: usb.cpp:44
bool get(int index) volatile
Definition: gpio.h:49
Definition: otg.h:94
void set(Register< T > value) volatile
Definition: register.h:12
Definition: otg.h:85
Definition: gpio.h:47
void clearEnumerationInterrupt()
Definition: usb.cpp:23
void shutdownGPIO()
Definition: usb.cpp:86
void setDSPD(DSPD s) volatile
Definition: otg.h:90
void initGPIO()
Definition: usb.cpp:61
Definition: app.cpp:5
void enable()
Definition: usb.cpp:27
void disable()
Definition: usb.cpp:32
bool isEnumerated()
Definition: usb.cpp:16
Definition: otg.h:79
void shutdown()
Definition: usb.cpp:49
Definition: gpio.h:95
GPIO group() const
Definition: gpio.h:98
Definition: otg.h:6
void setMode(int index, Mode mode) volatile
Definition: gpio.h:17
Definition: backlight.h:6
void initOTG()
Definition: usb.cpp:94
void set(int index, bool state) volatile
Definition: gpio.h:50
constexpr GPIO GPIOC(2)