source: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/USB/samd21_device.c@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 11.9 KB
Line 
1/* ----------------------------------------------------------------------------
2 * SAM Software Package License
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2011-2012, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following condition is met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30#include <stdio.h>
31#include <stdint.h>
32#include <string.h>
33
34#include "variant.h"
35#include "USB/USB_device.h"
36#include "USB/samd21_device.h"
37#include "sam.h"
38
39#ifdef __cplusplus
40extern "C"{
41#endif // __cplusplus
42
43#ifdef SAMD_SERIES
44
45//#define TRACE_DEVICE(x) x
46#define TRACE_DEVICE(x)
47
48__attribute__((__aligned__(4))) __attribute__((__section__(".bss_hram0"))) uint8_t udd_ep_out_cache_buffer[4][64];
49__attribute__((__aligned__(4))) __attribute__((__section__(".bss_hram0"))) uint8_t udd_ep_in_cache_buffer[4][128];
50
51/**
52 * USB SRAM data containing pipe descriptor table
53 * The content of the USB SRAM can be :
54 * - modified by USB hardware interface to update pipe status.
55 * Thereby, it is read by software.
56 * - modified by USB software to control pipe.
57 * Thereby, it is read by hardware.
58 * This data section is volatile.
59 */
60 __attribute__((__aligned__(4))) UsbDeviceDescriptor usb_endpoint_table[USB_EPT_NUM];
61
62// NVM Software Calibration Area Mapping
63// USB TRANSN calibration value. Should be written to the USB PADCAL register.
64#define NVM_USB_PAD_TRANSN_POS 45
65#define NVM_USB_PAD_TRANSN_SIZE 5
66// USB TRANSP calibration value. Should be written to the USB PADCAL register.
67#define NVM_USB_PAD_TRANSP_POS 50
68#define NVM_USB_PAD_TRANSP_SIZE 5
69// USB TRIM calibration value. Should be written to the USB PADCAL register.
70#define NVM_USB_PAD_TRIM_POS 55
71#define NVM_USB_PAD_TRIM_SIZE 3
72
73void UDD_Init(void)
74{
75 uint32_t pad_transn;
76 uint32_t pad_transp;
77 uint32_t pad_trim;
78 uint32_t i;
79
80 /* Enable USB clock */
81 PM->APBBMASK.reg |= PM_APBBMASK_USB;
82
83 /* Set up the USB DP/DN pins */
84 PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
85 PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
86 PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
87 PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
88 PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
89 PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
90
91 /* ----------------------------------------------------------------------------------------------
92 * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
93 */
94 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( 6 ) | // Generic Clock Multiplexer 6
95 GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
96 GCLK_CLKCTRL_CLKEN ;
97
98 while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
99 {
100 /* Wait for synchronization */
101 }
102
103 /* Reset */
104 USB->DEVICE.CTRLA.bit.SWRST = 1;
105 while (USB->DEVICE.SYNCBUSY.bit.SWRST) {
106 /* Sync wait */
107 }
108
109 udd_enable();
110
111 /* Load Pad Calibration */
112 pad_transn =( *((uint32_t *)(NVMCTRL_OTP4) // Non-Volatile Memory Controller
113 + (NVM_USB_PAD_TRANSN_POS / 32))
114 >> (NVM_USB_PAD_TRANSN_POS % 32))
115 & ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
116
117 if (pad_transn == 0x1F) { // maximum value (31)
118 pad_transn = 5;
119 }
120
121 USB->DEVICE.PADCAL.bit.TRANSN = pad_transn;
122
123 pad_transp =( *((uint32_t *)(NVMCTRL_OTP4)
124 + (NVM_USB_PAD_TRANSP_POS / 32))
125 >> (NVM_USB_PAD_TRANSP_POS % 32))
126 & ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
127
128 if (pad_transp == 0x1F) { // maximum value (31)
129 pad_transp = 29;
130 }
131
132 USB->DEVICE.PADCAL.bit.TRANSP = pad_transp;
133
134 pad_trim =( *((uint32_t *)(NVMCTRL_OTP4)
135 + (NVM_USB_PAD_TRIM_POS / 32))
136 >> (NVM_USB_PAD_TRIM_POS % 32))
137 & ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
138
139 if (pad_trim == 0x7) { // maximum value (7)
140 pad_trim = 3;
141 }
142
143 USB->DEVICE.PADCAL.bit.TRIM = pad_trim;
144
145 /* Set the configuration */
146 udd_force_device_mode();
147 udd_device_run_in_standby();
148 // Set address of USB SRAM
149 USB->DEVICE.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]);
150 // For USB_SPEED_FULL
151 udd_force_full_speed();
152 for (i = 0; i < sizeof(usb_endpoint_table)/4; i++) {
153 (*(uint32_t *)((uint32_t *)(&usb_endpoint_table[0])+i)) = 0;
154 }
155
156 // Configure interrupts
157 NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
158 NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
159}
160
161void UDD_Attach(void)
162{
163 TRACE_DEVICE(printf("=> UDD_Attach\r\n");)
164
165 // Authorize attach if Vbus is present
166 udd_attach_device();
167
168 // Enable USB line events
169 udd_enable_reset_interrupt();
170
171 // usefull for debug
172 udd_enable_sof_interrupt();
173}
174
175void UDD_Detach(void)
176{
177 TRACE_DEVICE(printf("=> UDD_Detach\r\n");)
178 udd_detach_device();
179}
180
181void send_zlp(void)
182{
183 /* Set the byte count as zero */
184 usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0;
185}
186
187
188void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg )
189{
190 TRACE_DEVICE(printf("=> UDD_InitEP : init EP %lu\r\n", (unsigned long)ul_ep_nb);)
191
192 if( ul_ep_cfg == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0)) )
193 {
194 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(4);
195 /* Set maximum packet size as 8 bytes */
196 usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0; // 8 bytes
197 /* Configure the data buffer */
198 usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[ul_ep_nb];
199 }
200 else if( ul_ep_cfg == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0)) )
201 {
202 /* Configure BULK OUT endpoint for CDC Data interface*/
203 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(3);
204 /* Set maximum packet size as 64 bytes */
205 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.SIZE = 0x3; // for 64 bytes
206 /* Configure the data buffer */
207 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[ul_ep_nb];
208
209 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 64;
210 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
211 // NACK if not ready
212 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
213 }
214 else if( ul_ep_cfg == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)) )
215 {
216 /* Configure BULK IN endpoint for CDC Data interface */
217 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(3);
218 /* Set maximum packet size as 64 bytes */
219 usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0x3; // for 64 bytes
220 /* Configure the data buffer */
221 usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[ul_ep_nb];
222 // NACK if not ready
223 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
224 }
225 else if( ul_ep_cfg == USB_ENDPOINT_TYPE_CONTROL )
226 {
227 /* Configure CONTROL endpoint */
228 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(1) | USB_DEVICE_EPCFG_EPTYPE1(1);
229 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
230 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
231
232 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
233 usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].PCKSIZE.reg &= ~USB_DEVICE_PCKSIZE_AUTO_ZLP;
234
235 /* Set maximum packet size as 64 bytes */
236 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.SIZE = 0x3; // for 64 bytes
237 usb_endpoint_table[ul_ep_nb].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0x3; // for 64 bytes
238
239 /* get endpoint configuration from setting register */
240 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[0];
241 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 16;
242 usb_endpoint_table[ul_ep_nb].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
243
244 // NACK if not ready
245 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
246 USB->DEVICE.DeviceEndpoint[ul_ep_nb].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
247 }
248}
249
250
251// Send packet.
252void UDD_ClearIN(void)
253{
254 USB->DEVICE.DeviceEndpoint[EP0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY;
255}
256
257
258
259uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len)
260{
261 memcpy(&udd_ep_in_cache_buffer[ep], data, len);
262
263 /* Get endpoint configuration from setting register */
264 usb_endpoint_table[ep].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[ep];
265 usb_endpoint_table[ep].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
266 usb_endpoint_table[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = len;
267
268 return len;
269}
270
271uint8_t UDD_Recv8(uint32_t ep)
272{
273 TRACE_DEVICE(printf("=> UDD_Recv8 : ep=%d\r\n", (char)ep);)
274
275 usb_endpoint_table[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[ep];
276 usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 8;
277 usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
278 USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
279 TRACE_DEVICE(printf("=> UDD_Recv8 : data=%lu\r\n", (unsigned long)data);)
280
281 /* Wait for transfer to complete */
282 while (!( USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0 ));
283 /* Clear Transfer complete 0 flag */
284 USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0 = 1;
285
286 return udd_ep_out_cache_buffer[ep][0];
287}
288
289void UDD_Recv(uint32_t ep, uint8_t** ppData)
290{
291 *ppData = udd_ep_out_cache_buffer[ep];
292}
293
294void UDD_Stall(uint32_t ep)
295{
296 uint8_t ep_num = ep;
297
298 // Stall endpoint
299 USB->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
300}
301
302uint32_t UDD_FifoByteCount(uint32_t ep)
303{
304 return ((uint16_t)(usb_endpoint_table[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT));
305}
306
307void UDD_ReleaseRX(uint32_t ep)
308{
309 TRACE_DEVICE(puts("=> UDD_ReleaseRX\r\n");)
310 USB->DEVICE.DeviceEndpoint[ep].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
311 USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
312}
313
314void UDD_ReleaseTX(uint32_t ep)
315{
316 TRACE_DEVICE(printf("=> UDD_ReleaseTX ep=%lu\r\n", (unsigned long)ep);)
317 USB->DEVICE.DeviceEndpoint[ep].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK1RDY;
318 USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
319}
320
321void UDD_SetAddress(uint32_t addr)
322{
323 TRACE_DEVICE(printf("=> UDD_SetAddress : setting address to %lu\r\n", (unsigned long)addr);)
324
325 /* Set the byte count as zero */
326 usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0;
327 /* Clear the transfer complete flag */
328 USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT1 = 1;
329 /* Set the bank as ready */
330 USB->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.BK1RDY = 1;
331
332 /* Wait for transfer to complete */
333 while (!( USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT1 )) {}
334
335 udd_configure_address(addr);
336}
337
338uint32_t UDD_GetFrameNumber(void)
339{
340 return udd_frame_number();
341}
342
343#ifdef __cplusplus
344}
345#endif
346
347#endif /* SAMD_SERIES */
348
Note: See TracBrowser for help on using the repository browser.