Skip to content

Commit 2b819b3

Browse files
committed
Add USBPhy template
Add a template for implementing a USBPhy.
1 parent e8934e4 commit 2b819b3

File tree

2 files changed

+375
-0
lines changed

2 files changed

+375
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2018-2018 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef USBPHYHW_H
18+
#define USBPHYHW_H
19+
20+
#include "mbed.h"
21+
#include "USBPhy.h"
22+
23+
24+
class USBPhyHw : public USBPhy {
25+
public:
26+
USBPhyHw();
27+
virtual ~USBPhyHw();
28+
virtual void init(USBPhyEvents *events);
29+
virtual void deinit();
30+
virtual bool powered();
31+
virtual void connect();
32+
virtual void disconnect();
33+
virtual void configure();
34+
virtual void unconfigure();
35+
virtual void sof_enable();
36+
virtual void sof_disable();
37+
virtual void set_address(uint8_t address);
38+
virtual void remote_wakeup();
39+
virtual const usb_ep_table_t* endpoint_table();
40+
41+
virtual uint32_t ep0_set_max_packet(uint32_t max_packet);
42+
virtual void ep0_setup_read_result(uint8_t *buffer, uint32_t size);
43+
virtual void ep0_read(uint8_t *data, uint32_t size);
44+
virtual uint32_t ep0_read_result();
45+
virtual void ep0_write(uint8_t *buffer, uint32_t size);
46+
virtual void ep0_stall();
47+
48+
virtual bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type);
49+
virtual void endpoint_remove(usb_ep_t endpoint);
50+
virtual void endpoint_stall(usb_ep_t endpoint);
51+
virtual void endpoint_unstall(usb_ep_t endpoint);
52+
53+
virtual bool endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size);
54+
virtual uint32_t endpoint_read_result(usb_ep_t endpoint);
55+
virtual bool endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size);
56+
virtual void endpoint_abort(usb_ep_t endpoint);
57+
58+
virtual void process();
59+
60+
private:
61+
USBPhyEvents *events;
62+
63+
static void _usbisr(void);
64+
};
65+
66+
#endif
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2018-2018 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "USBPhyHw.h"
18+
19+
static USBPhyHw *instance;
20+
21+
USBPhy *get_usb_phy()
22+
{
23+
static USBPhyHw usbphy;
24+
return &usbphy;
25+
}
26+
27+
USBPhyHw::USBPhyHw(): events(NULL)
28+
{
29+
30+
}
31+
32+
USBPhyHw::~USBPhyHw()
33+
{
34+
35+
}
36+
37+
void USBPhyHw::init(USBPhyEvents *events)
38+
{
39+
this->events = events;
40+
41+
// Disable IRQ
42+
NVIC_DisableIRQ(USB_IRQn);
43+
44+
// TODO - Setup clocks
45+
46+
// TODO - Enable USB module
47+
48+
// Enable IRQ
49+
NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
50+
NVIC_EnableIRQ(USB_IRQn);
51+
}
52+
53+
void USBPhyHw::deinit()
54+
{
55+
// Disconnect and disable interrupt
56+
disconnect();
57+
NVIC_DisableIRQ(USB_IRQn);
58+
}
59+
60+
bool USBPhyHw::powered()
61+
{
62+
// TODO - return true if powered false otherwise. Devices which don't support
63+
// this should always return true
64+
return true;
65+
}
66+
67+
void USBPhyHw::connect()
68+
{
69+
// TODO - Enable endpoint interrupts
70+
71+
// TODO - Enable pullup on D+
72+
}
73+
74+
void USBPhyHw::disconnect()
75+
{
76+
// TODO - Disable all endpoints
77+
78+
// TODO - Clear all endpoint interrupts
79+
80+
// TODO - Disable pullup on D+
81+
}
82+
83+
void USBPhyHw::configure()
84+
{
85+
// TODO - set device to configured. Most device will not need this
86+
}
87+
88+
void USBPhyHw::unconfigure()
89+
{
90+
// TODO - set device to unconfigured. Most device will not need this
91+
}
92+
93+
void USBPhyHw::sof_enable()
94+
{
95+
// TODO - Enable SOF interrupt
96+
}
97+
98+
void USBPhyHw::sof_disable()
99+
{
100+
// TODO - Disable SOF interrupt
101+
}
102+
103+
void USBPhyHw::set_address(uint8_t address)
104+
{
105+
// TODO - set the device address. Address must take effect
106+
// after the status phase of the current transfer
107+
}
108+
109+
void USBPhyHw::remote_wakeup()
110+
{
111+
// TODO - Sent remote wakeup over USB lines (if supported)
112+
}
113+
114+
const usb_ep_table_t *USBPhyHw::endpoint_table()
115+
{
116+
// TODO - Update the endpoint table for what your device supports
117+
118+
static const usb_ep_table_t template_table = {
119+
4096 - 32 * 4, // 32 words for endpoint buffers
120+
// +3 based added to interrupt and isochronous to ensure enough
121+
// space for 4 byte alignment
122+
{
123+
{USB_EP_ATTR_ALLOW_CTRL | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 0},
124+
{USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
125+
{USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0},
126+
{USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
127+
{USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
128+
{USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0},
129+
{USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
130+
{USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
131+
{USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0},
132+
{USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
133+
{USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
134+
{USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0},
135+
{USB_EP_ATTR_ALLOW_ISO | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
136+
{USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_DIR_IN_AND_OUT, 1, 3},
137+
{USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0},
138+
{USB_EP_ATTR_ALLOW_BULK | USB_EP_ATTR_DIR_IN_AND_OUT, 2, 0}
139+
}
140+
};
141+
return &lpc_table;
142+
}
143+
144+
uint32_t USBPhyHw::ep0_set_max_packet(uint32_t max_packet)
145+
{
146+
// TODO - set endpoint 0 size and return this size
147+
return 64;
148+
}
149+
150+
// read setup packet
151+
void USBPhyHw::ep0_setup_read_result(uint8_t *buffer, uint32_t size)
152+
{
153+
// TODO - read up to size bytes of the setup packet
154+
}
155+
156+
void USBPhyHw::ep0_read(uint8_t *data, uint32_t size)
157+
{
158+
// TODO - setup data buffer to receive next endpoint 0 OUT packet
159+
}
160+
161+
uint32_t USBPhyHw::ep0_read_result()
162+
{
163+
// TODO - return the size of the last OUT packet received on endpoint 0
164+
return 0;
165+
}
166+
167+
void USBPhyHw::ep0_write(uint8_t *buffer, uint32_t size)
168+
{
169+
// TODO - start transferring buffer on endpoint 0 IN
170+
}
171+
172+
void USBPhyHw::ep0_stall()
173+
{
174+
// TODO - protocol stall endpoint 0. This stall must be automatically
175+
// cleared by the next setup packet
176+
}
177+
178+
bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type)
179+
{
180+
// TODO - enable this endpoint
181+
182+
return true;
183+
}
184+
185+
void USBPhyHw::endpoint_remove(usb_ep_t endpoint)
186+
{
187+
// TODO - disable and remove this endpoint
188+
}
189+
190+
void USBPhyHw::endpoint_stall(usb_ep_t endpoint)
191+
{
192+
// TODO - stall this endpoint until it is explicitly cleared
193+
}
194+
195+
void USBPhyHw::endpoint_unstall(usb_ep_t endpoint)
196+
{
197+
// TODO - unstall this endpoint
198+
}
199+
200+
bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size)
201+
{
202+
// TODO - setup data buffer to receive next endpoint OUT packet and return true if successful
203+
return true;
204+
}
205+
206+
uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint)
207+
{
208+
// TODO - return the size of the last OUT packet received on endpoint
209+
}
210+
211+
bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size)
212+
{
213+
// TODO - start transferring buffer on endpoint IN
214+
215+
return true;
216+
}
217+
218+
void USBPhyHw::endpoint_abort(usb_ep_t endpoint)
219+
{
220+
// TODO - stop the current transfer on this endpoint and don't call the IN or OUT callback
221+
}
222+
223+
void USBPhyHw::process()
224+
{
225+
// TODO - update register for your mcu
226+
227+
uint8_t stat = USB0->STAT;
228+
229+
USB0->STAT = stat; // Clear pending interrupts
230+
231+
// reset interrupt
232+
if (stat & USB_STAT_RESET_MASK) {
233+
234+
// TODO - disable all endpoints
235+
236+
// TODO - clear all endpoint interrupts
237+
238+
// TODO - enable control endpoint
239+
240+
// reset bus for USBDevice layer
241+
events->reset();
242+
243+
// Re-enable interrupt
244+
NVIC_ClearPendingIRQ(USB_IRQn);
245+
NVIC_EnableIRQ(USB_IRQn);
246+
return;
247+
}
248+
249+
// power applied
250+
if (stat & USB_STAT_POWERED) {
251+
events->powered(true);
252+
}
253+
254+
// power lost
255+
if (stat & USB_STAT_UNPOWERED) {
256+
events->powered(false);
257+
}
258+
259+
// sleep interrupt
260+
if (stat & USB_STAT_SUSPEND_MASK) {
261+
events->suspend(true);
262+
}
263+
264+
// resume interrupt
265+
if (stat & USB_STAT_RESUME_MASK) {
266+
events->suspend(false);
267+
}
268+
269+
// sof interrupt
270+
if (stat & USB_STAT_SOF_MASK) {
271+
// SOF event, read frame number
272+
events->sof(USB0->FRAME);
273+
}
274+
275+
// endpoint interrupt
276+
if (stat & USB_STAT_EP_MASK) {
277+
uint32_t ep_pending = USB->EP;
278+
279+
// TODO - call endpoint 0 IN callback if pending
280+
events->ep0_in();
281+
282+
// TODO - call endpoint 0 OUT callback if pending
283+
events->ep0_out();
284+
285+
// TODO - call endpoint 0 SETUP callback if pending
286+
events->ep0_setup();
287+
288+
for (int i = 0; i < 16; i++) {
289+
// TODO - call endpoint i IN callback if pending
290+
events->in(0x80 | i);
291+
}
292+
293+
for (int i = 0; i < 16; i++) {
294+
// TODO - call endpoint i OUT callback if pending
295+
events->out();
296+
}
297+
298+
USB->EP = ep_pending; // clear pending
299+
}
300+
301+
// Re-enable interrupt
302+
NVIC_ClearPendingIRQ(USB_IRQn);
303+
NVIC_EnableIRQ(USB_IRQn);
304+
}
305+
306+
void USBPhyHw::_usbisr(void) {
307+
NVIC_DisableIRQ(USB_IRQn);
308+
instance->events->start_process();
309+
}

0 commit comments

Comments
 (0)