Hanna
Sourcecode Kontrollplatine
usb_xm.c
gehe zur Dokumentation dieser Datei
1 
14 #include <util/atomic.h>
15 #include <avr/io.h>
16 #include "usb_xm.h"
17 
20 // IRQ's
23 
25 // global IRQ
27 ISR(USB_BUSEVENT_vect)
28 {
29  if ( USB.INTFLAGSACLR & USB_SOFIF_bm )
30  {
31  USB.INTFLAGSACLR = USB_SOFIF_bm;
32  }
33  else if ( USB.INTFLAGSACLR & (USB_CRCIF_bm | USB_UNFIF_bm | USB_OVFIF_bm) )
34  {
35  USB.INTFLAGSACLR = (USB_CRCIF_bm | USB_UNFIF_bm | USB_OVFIF_bm);
36  }
37  else if ( USB.INTFLAGSACLR & USB_STALLIF_bm )
38  {
39  USB.INTFLAGSACLR = USB_STALLIF_bm;
40  }
41  else
42  {
43  if ( USB.INTFLAGSACLR & USB_SUSPENDIF_bm )
44  {
46  }
47 
48  if ( USB.INTFLAGSACLR & USB_RESUMEIF_bm )
49  {
51  }
52 
53  if ( USB.INTFLAGSACLR & USB_RSTIF_bm )
54  {
55  USB.ADDR = 0;
56  USB_DeviceState = DEVICE_STATE_Default;
57  USB_ResetInterface ();
59  }
60 
61  USB.INTFLAGSACLR = USB_SUSPENDIF_bm | USB_RESUMEIF_bm | USB_RSTIF_bm;
62  USB_Evt_Task ();
63  }
64 }
65 
67 // irq for transaktion complete
69 ISR(USB_TRNCOMPL_vect)
70 {
71  USB.FIFOWP = 0;
72  USB.INTFLAGSBCLR = USB_SETUPIF_bm | USB_TRNIF_bm;
73  USB_Task ();
74 }
75 
78 // USB-Functions
81 inline bool USB_handleSetAddress ( USB_Request_Header_t* req )
82 {
83  uint8_t DeviceAddress = (req->wValue & 0x7F);
84  USB_EP_pair_t* pair = &endpoints[0];
85  USB_EP_t* e = &pair->ep[1];
86  USB_EP_t* b = &pair->ep[1];
87 
88  LACR16( &endpoints[0].out.STATUS, USB_EP_SETUP_bm | USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm | USB_EP_OVF_bm );
89 
90  b->DATAPTR = (unsigned) ep0_buf_in;
91  b->CNT = 0;
92  LACR16( &(e->STATUS), USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm );
93 
94  while ( !(e->STATUS & USB_EP_TRNCOMPL0_bm) )
95  {
96  };
97 
98  USB.ADDR = DeviceAddress;
99  USB_DeviceState = (DeviceAddress) ? DEVICE_STATE_Addressed : DEVICE_STATE_Default;
100  return true;
101 }
102 
103 #if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
104 inline void USB_Device_GetSerialString ( uint16_t* const UnicodeString ) ATTR_NON_NULL_PTR_ARG(1);
105 inline void USB_Device_GetSerialString ( uint16_t* const UnicodeString )
106 {
107  //uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
108  //GlobalInterruptDisable();
109 
110  uint8_t SigReadAddress = INTERNAL_SERIAL_START_ADDRESS;
111 
112  for ( uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++ )
113  {
114  uint8_t SerialByte;
115 
116  NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
117  SerialByte = pgm_read_byte( SigReadAddress );
118  NVM_CMD = NVM_CMD_NO_OPERATION_gc;
119 
120  if ( SerialCharNum & 0x01 )
121  {
122  SerialByte >>= 4;
123  SigReadAddress++;
124  }
125 
126  SerialByte &= 0x0F;
127 
128  UnicodeString[SerialCharNum] = ((SerialByte >= 10) ? (('A' - 10) + SerialByte) : ('0' + SerialByte));
129  }
130 
131  //SetGlobalInterruptMask(CurrentGlobalInt);
132 }
133 
134 inline void USB_Device_GetInternalSerialDescriptor ( void )
135 {
136  USB_EP_pair_t* pair = &endpoints[0];
137  USB_EP_t* e = &pair->ep[1];
138  USB_EP_t* b = &pair->ep[1];
139 
140  struct
141  {
142  USB_Descriptor_Header_t Header;
143  uint16_t UnicodeString[INTERNAL_SERIAL_LENGTH_BITS / 4];
144  }* SignatureDescriptor = (void*) ep0_buf_in;
145 
146  SignatureDescriptor->Header.Type = DTYPE_String;
147  SignatureDescriptor->Header.Size = USB_STRING_LEN( INTERNAL_SERIAL_LENGTH_BITS / 4 );
148 
149  USB_Device_GetSerialString ( SignatureDescriptor->UnicodeString );
150 
151  b->DATAPTR = (unsigned) ep0_buf_in;
152  b->CNT = sizeof(*SignatureDescriptor);
153  LACR16( &(e->STATUS), USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm );
154 }
155 #endif
156 
157 inline bool USB_handleGetDescriptor ( USB_Request_Header_t* req )
158 {
159  const void* DescriptorPointer;
160  uint16_t DescriptorSize;
161  NVM.CMD = NVM_CMD_NO_OPERATION_gc;
162 
163 #if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
164  if ( req->wValue == ((DTYPE_String << 8) | USE_INTERNAL_SERIAL) )
165  {
166  USB_Device_GetInternalSerialDescriptor ();
167  return true;
168  }
169 #endif
170 
171  if ( (DescriptorSize = CALLBACK_USB_GetDescriptor ( req->wValue, req->wIndex, &DescriptorPointer )) )
172  {
173  if ( DescriptorSize > req->wLength ) DescriptorSize = req->wLength;
174  USB_ep0_send_progmem ( DescriptorPointer, DescriptorSize );
175  return true;
176  }
177  return false;
178 }
179 
180 inline bool USB_handleSetConfiguration ( USB_Request_Header_t* req )
181 {
182  USB_Descriptor_Device_t* DevDescriptorPtr;
183  USB_EP_pair_t* pair = &endpoints[0];
184  USB_EP_t* e = &pair->ep[1];
185  USB_EP_t* b = &pair->ep[1];
186 
187  uint8_t r = CALLBACK_USB_GetDescriptor ( (DTYPE_Device << 8), 0, (void*) &DevDescriptorPtr );
188  if ( r == NO_DESCRIPTOR ) return false;
189 
190  NVM.CMD = NVM_CMD_NO_OPERATION_gc;
191  uint8_t num_configs = pgm_read_byte( &DevDescriptorPtr->NumberOfConfigurations );
192 
193  if ( (uint8_t) req->wValue > num_configs ) return false;
194 
195  b->DATAPTR = (unsigned) ep0_buf_in;
196  b->CNT = 0;
197  LACR16( &(e->STATUS), USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm );
198 
199  USB_Device_ConfigurationNumber = (uint8_t) (req->wValue);
200 
201  if ( USB_Device_ConfigurationNumber )
202  USB_DeviceState = DEVICE_STATE_Configured;
203  else
204  USB_DeviceState = (USB.ADDR) ? DEVICE_STATE_Configured : DEVICE_STATE_Powered;
205 
206  EVENT_USB_Device_ConfigurationChanged ( USB_Device_ConfigurationNumber );
207  return true;
208 }
209 
210 bool USB_HandleSetup ( void )
211 {
212  USB_Request_Header_t* req = (void *) ep0_buf_out;
213  USB_EP_pair_t* pair = &endpoints[0];
214  USB_EP_t* e __attribute__ ((unused)) = &pair->ep[1];
215  USB_EP_t* b = &pair->ep[1];
216 
217  if ( (req->bmRequestType & CONTROL_REQTYPE_TYPE) == REQTYPE_STANDARD )
218  {
219  switch (req->bRequest)
220  {
221  case REQ_GetStatus:
222  ep0_buf_in[0] = 0;
223  ep0_buf_in[1] = 0;
224  b->DATAPTR = (unsigned) ep0_buf_in;
225  b->CNT = 2;
226  LACR16( &(e->STATUS), USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm );
227  return true;
228  case REQ_ClearFeature:
229  case REQ_SetFeature:
230  b->DATAPTR = (unsigned) ep0_buf_in;
231  b->CNT = 0;
232  LACR16( &(e->STATUS), USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm );
233  return true;
234  case REQ_SetAddress:
235  return USB_handleSetAddress ( req );
236  case REQ_GetDescriptor:
237  return USB_handleGetDescriptor ( req );
239  ep0_buf_in[0] = USB_Device_ConfigurationNumber;
240  b->DATAPTR = (unsigned) ep0_buf_in;
241  b->CNT = 1;
242  LACR16( &(e->STATUS), USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm );
243  return true;
245  return USB_handleSetConfiguration ( req );
246  case REQ_SetInterface:
247  if ( EVENT_USB_Device_SetInterface ( req->wIndex, req->wValue ) )
248  {
249  b->DATAPTR = (unsigned) ep0_buf_in;
250  b->CNT = 0;
251  LACR16( &(e->STATUS), USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm );
252  return true;
253  }
254  break;
255  case REQ_GetInterface:
256  return false;
257  }
258  }
259 
260  return EVENT_USB_Device_ControlRequest ( req );
261 }
262 
263 volatile uint8_t USB_DeviceState;
264 volatile uint8_t USB_Device_ConfigurationNumber;
265 
266 void USB_xm_Init ( void )
267 {
268  //uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
269  //GlobalInterruptDisable();
270 
271  NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
272  USB.CAL0 = pgm_read_byte( offsetof(NVM_PROD_SIGNATURES_t, USBCAL0) );
273  NVM_CMD = NVM_CMD_NO_OPERATION_gc;
274 
275  NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
276  USB.CAL1 = pgm_read_byte( offsetof(NVM_PROD_SIGNATURES_t, USBCAL1) );
277  NVM_CMD = NVM_CMD_NO_OPERATION_gc;
278 
279  //SetGlobalInterruptMask(CurrentGlobalInt);
280 
281  USB_ResetInterface ();
282 }
283 
284 void USB_ResetInterface ( void )
285 {
286 
287  CLK.USBCTRL = ((((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp) | CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm);
288  USB.EPPTR = (unsigned) &endpoints;
289  USB.ADDR = 0;
290 
291  endpoints[0].out.STATUS = 0;
292  endpoints[0].out.CTRL = USB_EP_TYPE_CONTROL_gc | USB_EP_size_to_gc( USB_DEF_EP0_SIZE );
293  endpoints[0].out.DATAPTR = (unsigned) &ep0_buf_out;
294  endpoints[0].in.STATUS = USB_EP_BUSNACK0_bm;
295  endpoints[0].in.CTRL = USB_EP_TYPE_CONTROL_gc | USB_EP_size_to_gc( USB_DEF_EP0_SIZE );
296  endpoints[0].in.DATAPTR = (unsigned) &ep0_buf_in;
297 
298  USB.CTRLA = USB_ENABLE_bm | USB_SPEED_bm | (USB_DEF_EP_MAX - 1);
299 
300 // USB_Attach();
301  USB.CTRLB |= USB_ATTACH_bm;
302 }
303 
304 void USB_ep0_send_progmem ( const uint8_t* addr, uint16_t size )
305 {
306  uint8_t *buf = ep0_buf_in;
307  uint16_t remaining = size;
308  NVM.CMD = NVM_CMD_NO_OPERATION_gc;
309 
310  USB_EP_pair_t* pair = &endpoints[0];
311  USB_EP_t* e = &pair->ep[1];
312  USB_EP_t* b = &pair->ep[1];
313 
314  while ( remaining-- )
315  {
316  *buf++ = pgm_read_byte( addr++ );
317  }
318 
319  b->DATAPTR = (unsigned) ep0_buf_in;
320  b->CNT = size;
321  LACR16( &(e->STATUS), USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm );
322 }
323 
324 void USB_ConfigureClock ( void )
325 {
326  // Configure DFLL for 48MHz, calibrated by USB SOF
327  OSC.DFLLCTRL = OSC_RC32MCREF_USBSOF_gc;
328  NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
329  DFLLRC32M.CALB = pgm_read_byte( offsetof(NVM_PROD_SIGNATURES_t, USBRCOSC) );
330  NVM_CMD = NVM_CMD_NO_OPERATION_gc;
331  DFLLRC32M.COMP1 = 0x1B; //Xmega AU manual, 4.17.19
332  DFLLRC32M.COMP2 = 0xB7;
333  DFLLRC32M.CTRL = DFLL_ENABLE_bm;
334 
335  CCP = CCP_IOREG_gc; //Security Signature to modify clock
336  OSC.CTRL = OSC_RC32MEN_bm | OSC_RC2MEN_bm; // enable internal 32MHz oscillator
337 
338  while ( !(OSC.STATUS & OSC_RC32MRDY_bm) )
339  ; // wait for oscillator ready
340 
341  OSC.PLLCTRL = OSC_PLLSRC_RC2M_gc | 16; // 2MHz * 16 = 32MHz
342 
343  CCP = CCP_IOREG_gc;
344  OSC.CTRL = OSC_RC32MEN_bm | OSC_PLLEN_bm | OSC_RC2MEN_bm; // Enable PLL
345 
346  while ( !(OSC.STATUS & OSC_PLLRDY_bm) )
347  ; // wait for PLL ready
348 
349  DFLLRC2M.CTRL = DFLL_ENABLE_bm;
350 
351  CCP = CCP_IOREG_gc; //Security Signature to modify clock
352  CLK.CTRL = CLK_SCLKSEL_PLL_gc; // Select PLL
353  CLK.PSCTRL = 0x00; // No peripheral clock prescaler
354 }
355 
358 // USB Tasks
361 void USB_Evt_Task ( void )
362 {
363  if ( USB.STATUS & USB_BUSRST_bm )
364  {
365  USB.STATUS &= ~USB_BUSRST_bm;
366  USB_xm_Init ();
367  }
368 }
369 
371 // is call from irq
373 void USB_Task ( void )
374 {
375  // Read once to prevent race condition where SETUP packet is interpreted as OUT
376  uint8_t status = endpoints[0].out.STATUS;
377 
378  if ( status & USB_EP_SETUP_bm )
379  {
380  if ( !USB_HandleSetup () )
381  {
382  endpoints[0].out.CTRL |= USB_EP_STALL_bm;
383  endpoints[0].in.CTRL |= USB_EP_STALL_bm;
384  }
385  LACR16( &endpoints[0].out.STATUS, USB_EP_SETUP_bm | USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm | USB_EP_OVF_bm );
386  }
387  else if ( status & USB_EP_TRNCOMPL0_bm )
388  {
389  EVENT_USB_Device_ControlOUT ( (uint8_t *) ep0_buf_out, endpoints[0].out.CNT );
390  LACR16( &endpoints[0].out.STATUS, USB_EP_SETUP_bm | USB_EP_BUSNACK0_bm | USB_EP_TRNCOMPL0_bm | USB_EP_OVF_bm );
391  }
392 }
393 
void EVENT_USB_Device_WakeUp(void)
Definition: usb_cdc.c:208
bool EVENT_USB_Device_SetInterface(uint8_t interface, uint8_t altsetting)
Definition: usb_cdc.c:183
void EVENT_USB_Device_ControlOUT(uint8_t *data, uint8_t len)
Definition: usb_cdc.c:221
bool EVENT_USB_Device_ControlRequest(USB_Request_Header_t *req)
Definition: usb_cdc.c:239
void EVENT_USB_Device_Reset(void)
Definition: usb_cdc.c:215
void EVENT_USB_Device_Suspend(void)
Definition: usb_cdc.c:201
#define LACR16(addr, msk)
From Atmel: Macros for XMEGA instructions not yet supported by the toolchain.
Definition: usb_defaults.h:112
Bibliothek zur USB-Kommunikation von Jürgen W.
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, const void **const DescriptorAddress)
Definition: Descriptors.c:182
void EVENT_USB_Device_ConfigurationChanged(uint8_t config)
Definition: usb_cdc.c:191