-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathusb_xmega.c
95 lines (71 loc) · 2.92 KB
/
usb_xmega.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Minimal USB Stack for ATxmega32a4u and related
// http://nonolithlabs.com
// (C) 2011 Kevin Mehall (Nonolith Labs) <[email protected]>
//
// Heavily borrows from LUFA
// Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
//
// Licensed under the terms of the GNU GPLv3+
#include <avr/io.h>
#define DEFINE_EVENT_ALIASES
#include "usb.h"
uint8_t ep0_buf_in[USB_EP0SIZE];
uint8_t ep0_buf_out[USB_EP0SIZE];
USB_EP_pair_t endpoints[USB_MAXEP+1] GCC_FORCE_ALIGN_2;
volatile uint8_t USB_DeviceState;
volatile uint8_t USB_Device_ConfigurationNumber;
void USB_Init(){
//uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
//GlobalInterruptDisable();
NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
USB.CAL0 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL0));
NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
USB.CAL1 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL1));
//SetGlobalInterruptMask(CurrentGlobalInt);
USB_ResetInterface();
}
void USB_ResetInterface(){
//if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
// CLK.USBCTRL = ((((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp) | CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm);
//else
CLK.USBCTRL = ((((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp) | CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm);
USB.EPPTR = (unsigned) &endpoints;
USB.ADDR = 0;
endpoints[0].out.STATUS = 0;
endpoints[0].out.CTRL = USB_EP_TYPE_CONTROL_gc | USB_EP_size_to_gc(USB_EP0SIZE);
endpoints[0].out.DATAPTR = (unsigned) &ep0_buf_out;
endpoints[0].in.STATUS = USB_EP_BUSNACK0_bm;
endpoints[0].in.CTRL = USB_EP_TYPE_CONTROL_gc | USB_EP_size_to_gc(USB_EP0SIZE);
endpoints[0].in.DATAPTR = (unsigned) &ep0_buf_in;
USB.CTRLA = USB_ENABLE_bm | USB_SPEED_bm | USB_MAXEP;
USB_Attach();
}
void USB_ep0_send_progmem(const uint8_t* addr, uint16_t size){
uint8_t *buf = ep0_buf_in;
uint16_t remaining = size;
NVM.CMD = NVM_CMD_NO_OPERATION_gc;
while (remaining--){
*buf++ = pgm_read_byte(addr++);
}
USB_ep0_send(size);
}
void USB_ConfigureClock(){
// Configure DFLL for 48MHz, calibrated by USB SOF
OSC.DFLLCTRL = OSC_RC32MCREF_USBSOF_gc;
NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
DFLLRC32M.CALB = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBRCOSC));
DFLLRC32M.COMP1 = 0x1B; //Xmega AU manual, 4.17.19
DFLLRC32M.COMP2 = 0xB7;
DFLLRC32M.CTRL = DFLL_ENABLE_bm;
CCP = CCP_IOREG_gc; //Security Signature to modify clock
OSC.CTRL = OSC_RC32MEN_bm | OSC_RC2MEN_bm; // enable internal 32MHz oscillator
while(!(OSC.STATUS & OSC_RC32MRDY_bm)); // wait for oscillator ready
OSC.PLLCTRL = OSC_PLLSRC_RC2M_gc | 16; // 2MHz * 16 = 32MHz
CCP = CCP_IOREG_gc;
OSC.CTRL = OSC_RC32MEN_bm | OSC_PLLEN_bm | OSC_RC2MEN_bm ; // Enable PLL
while(!(OSC.STATUS & OSC_PLLRDY_bm)); // wait for PLL ready
DFLLRC2M.CTRL = DFLL_ENABLE_bm;
CCP = CCP_IOREG_gc; //Security Signature to modify clock
CLK.CTRL = CLK_SCLKSEL_PLL_gc; // Select PLL
CLK.PSCTRL = 0x00; // No peripheral clock prescaler
}