/ bootloaders / caterina / Caterina.c
Caterina.c
  1  /*
  2               LUFA Library
  3       Copyright (C) Dean Camera, 2011.
  4  
  5    dean [at] fourwalledcubicle [dot] com
  6             www.lufa-lib.org
  7  */
  8  
  9  /*
 10    Copyright 2011  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 11  
 12    Permission to use, copy, modify, distribute, and sell this
 13    software and its documentation for any purpose is hereby granted
 14    without fee, provided that the above copyright notice appear in
 15    all copies and that both that the copyright notice and this
 16    permission notice and warranty disclaimer appear in supporting
 17    documentation, and that the name of the author not be used in
 18    advertising or publicity pertaining to distribution of the
 19    software without specific, written prior permission.
 20  
 21    The author disclaim all warranties with regard to this
 22    software, including all implied warranties of merchantability
 23    and fitness.  In no event shall the author be liable for any
 24    special, indirect or consequential damages or any damages
 25    whatsoever resulting from loss of use, data or profits, whether
 26    in an action of contract, negligence or other tortious action,
 27    arising out of or in connection with the use or performance of
 28    this software.
 29  */
 30  
 31  /** \file
 32   *
 33   *  Main source file for the CDC class bootloader. This file contains the complete bootloader logic.
 34   */
 35  
 36  #define  INCLUDE_FROM_CATERINA_C
 37  #include "Caterina.h"
 38  
 39  /** Contains the current baud rate and other settings of the first virtual serial port. This must be retained as some
 40   *  operating systems will not open the port unless the settings can be set successfully.
 41   */
 42  static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
 43                                             .CharFormat  = CDC_LINEENCODING_OneStopBit,
 44                                             .ParityType  = CDC_PARITY_None,
 45                                             .DataBits    = 8                            };
 46  
 47  /** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
 48   *  and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
 49   *  command.)
 50   */
 51  static uint32_t CurrAddress;
 52  
 53  /** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
 54   *  via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an infinite
 55   *  loop until the AVR restarts and the application runs.
 56   */
 57  static bool RunBootloader = true;
 58  
 59  /* Pulse generation counters to keep track of the time remaining for each pulse type */
 60  #define TX_RX_LED_PULSE_PERIOD 100
 61  uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse
 62  uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse
 63  
 64  /* Bootloader timeout timer */
 65  #define TIMEOUT_PERIOD	8000
 66  uint16_t Timeout = 0;
 67  
 68  uint16_t bootKey = 0x7777;
 69  volatile uint16_t *const bootKeyPtr = (volatile uint16_t *)0x0800;
 70  
 71  void StartSketch(void)
 72  {
 73  	cli();
 74  	
 75  	/* Undo TIMER1 setup and clear the count before running the sketch */
 76  	TIMSK1 = 0;
 77  	TCCR1B = 0;
 78  	TCNT1H = 0;		// 16-bit write to TCNT1 requires high byte be written first
 79  	TCNT1L = 0;
 80  	
 81  	/* Relocate the interrupt vector table to the application section */
 82  	MCUCR = (1 << IVCE);
 83  	MCUCR = 0;
 84  
 85  	L_LED_OFF();
 86  	TX_LED_OFF();
 87  	RX_LED_OFF();
 88  
 89  	/* jump to beginning of application space */
 90  	__asm__ volatile("jmp 0x0000");
 91  }
 92  
 93  /*	Breathing animation on L LED indicates bootloader is running */
 94  uint16_t LLEDPulse;
 95  void LEDPulse(void)
 96  {
 97  	LLEDPulse++;
 98  	uint8_t p = LLEDPulse >> 8;
 99  	if (p > 127)
100  		p = 254-p;
101  	p += p;
102  	if (((uint8_t)LLEDPulse) > p)
103  		L_LED_OFF();
104  	else
105  		L_LED_ON();
106  }
107  
108  /** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
109   *  runs the bootloader processing routine until it times out or is instructed to exit.
110   */
111  int main(void)
112  {
113  	/* Save the value of the boot key memory before it is overwritten */
114  	uint16_t bootKeyPtrVal = *bootKeyPtr;
115  	*bootKeyPtr = 0;
116  
117  	/* Check the reason for the reset so we can act accordingly */
118  	uint8_t  mcusr_state = MCUSR;		// store the initial state of the Status register
119  	MCUSR = 0;							// clear all reset flags	
120  
121  	/* Watchdog may be configured with a 15 ms period so must disable it before going any further */
122  	wdt_disable();
123  	
124  	if (mcusr_state & (1<<EXTRF)) {
125  		// External reset -  we should continue to self-programming mode.
126  	} else if ((mcusr_state & (1<<PORF)) && (pgm_read_word(0) != 0xFFFF)) {		
127  		// After a power-on reset skip the bootloader and jump straight to sketch 
128  		// if one exists.	
129  		StartSketch();
130  	} else if ((mcusr_state & (1<<WDRF)) && (bootKeyPtrVal != bootKey) && (pgm_read_word(0) != 0xFFFF)) {	
131  		// If it looks like an "accidental" watchdog reset then start the sketch.
132  		StartSketch();
133  	}
134  	
135  	/* Setup hardware required for the bootloader */
136  	SetupHardware();
137  
138  	/* Enable global interrupts so that the USB stack can function */
139  	sei();
140  	
141  	Timeout = 0;
142  	
143  	while (RunBootloader)
144  	{
145  		CDC_Task();
146  		USB_USBTask();
147  		/* Time out and start the sketch if one is present */
148  		if (Timeout > TIMEOUT_PERIOD)
149  			RunBootloader = false;
150  
151  		LEDPulse();
152  	}
153  
154  	/* Disconnect from the host - USB interface will be reset later along with the AVR */
155  	USB_Detach();
156  
157  	/* Jump to beginning of application space to run the sketch - do not reset */	
158  	StartSketch();
159  }
160  
161  /** Configures all hardware required for the bootloader. */
162  void SetupHardware(void)
163  {
164  	/* Disable watchdog if enabled by bootloader/fuses */
165  	MCUSR &= ~(1 << WDRF);
166  	wdt_disable();
167  
168  	/* Disable clock division */
169  	clock_prescale_set(clock_div_1);
170  
171  	/* Relocate the interrupt vector table to the bootloader section */
172  	MCUCR = (1 << IVCE);
173  	MCUCR = (1 << IVSEL);
174  	
175  	LED_SETUP();
176  	CPU_PRESCALE(0); 
177  	L_LED_OFF();
178  	TX_LED_OFF();
179  	RX_LED_OFF();
180  	
181  	/* Initialize TIMER1 to handle bootloader timeout and LED tasks.  
182  	 * With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
183  	 * Our chosen compare match generates an interrupt every 1 ms.
184  	 * This interrupt is disabled selectively when doing memory reading, erasing,
185  	 * or writing since SPM has tight timing requirements.
186  	 */ 
187  	OCR1AH = 0;
188  	OCR1AL = 250;
189  	TIMSK1 = (1 << OCIE1A);					// enable timer 1 output compare A match interrupt
190  	TCCR1B = ((1 << CS11) | (1 << CS10));	// 1/64 prescaler on timer 1 input
191  
192  	/* Initialize USB Subsystem */
193  	USB_Init();
194  }
195  
196  //uint16_t ctr = 0;
197  ISR(TIMER1_COMPA_vect, ISR_BLOCK)
198  {
199  	/* Reset counter */
200  	TCNT1H = 0;
201  	TCNT1L = 0;
202  
203  	/* Check whether the TX or RX LED one-shot period has elapsed.  if so, turn off the LED */
204  	if (TxLEDPulse && !(--TxLEDPulse))
205  		TX_LED_OFF();
206  	if (RxLEDPulse && !(--RxLEDPulse))
207  		RX_LED_OFF();
208  	
209  	if (pgm_read_word(0) != 0xFFFF)
210  		Timeout++;
211  }
212  
213  /** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
214   *  to relay data to and from the attached USB host.
215   */
216  void EVENT_USB_Device_ConfigurationChanged(void)
217  {
218  	/* Setup CDC Notification, Rx and Tx Endpoints */
219  	Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
220  	                           ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
221  	                           ENDPOINT_BANK_SINGLE);
222  
223  	Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
224  	                           ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
225  	                           ENDPOINT_BANK_SINGLE);
226  
227  	Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
228  	                           ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
229  	                           ENDPOINT_BANK_SINGLE);
230  }
231  
232  /** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
233   *  the device from the USB host before passing along unhandled control requests to the library for processing
234   *  internally.
235   */
236  void EVENT_USB_Device_ControlRequest(void)
237  {
238  	/* Ignore any requests that aren't directed to the CDC interface */
239  	if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
240  	    (REQTYPE_CLASS | REQREC_INTERFACE))
241  	{
242  		return;
243  	}
244  
245  	/* Process CDC specific control requests */
246  	switch (USB_ControlRequest.bRequest)
247  	{
248  		case CDC_REQ_GetLineEncoding:
249  			if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
250  			{
251  				Endpoint_ClearSETUP();
252  
253  				/* Write the line coding data to the control endpoint */
254  				Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
255  				Endpoint_ClearOUT();
256  			}
257  
258  			break;
259  		case CDC_REQ_SetLineEncoding:
260  			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
261  			{
262  				Endpoint_ClearSETUP();
263  
264  				/* Read the line coding data in from the host into the global struct */
265  				Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
266  				Endpoint_ClearIN();
267  			}
268  
269  			break;
270  	}
271  }
272  
273  #if !defined(NO_BLOCK_SUPPORT)
274  /** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
275   *  on the AVR910 protocol command issued.
276   *
277   *  \param[in] Command  Single character AVR910 protocol command indicating what memory operation to perform
278   */
279  static void ReadWriteMemoryBlock(const uint8_t Command)
280  {
281  	uint16_t BlockSize;
282  	char     MemoryType;
283  
284  	bool     HighByte = false;
285  	uint8_t  LowByte  = 0;
286  
287  	BlockSize  = (FetchNextCommandByte() << 8);
288  	BlockSize |=  FetchNextCommandByte();
289  
290  	MemoryType =  FetchNextCommandByte();
291  
292  	if ((MemoryType != 'E') && (MemoryType != 'F'))
293  	{
294  		/* Send error byte back to the host */
295  		WriteNextResponseByte('?');
296  
297  		return;
298  	}
299  
300  	/* Disable timer 1 interrupt - can't afford to process nonessential interrupts
301  	 * while doing SPM tasks */
302  	TIMSK1 = 0;
303  
304  	/* Check if command is to read memory */
305  	if (Command == 'g')
306  	{		
307  		/* Re-enable RWW section */
308  		boot_rww_enable();
309  
310  		while (BlockSize--)
311  		{
312  			if (MemoryType == 'F')
313  			{
314  				/* Read the next FLASH byte from the current FLASH page */
315  				#if (FLASHEND > 0xFFFF)
316  				WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
317  				#else
318  				WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
319  				#endif
320  
321  				/* If both bytes in current word have been read, increment the address counter */
322  				if (HighByte)
323  				  CurrAddress += 2;
324  
325  				HighByte = !HighByte;
326  			}
327  			else
328  			{
329  				/* Read the next EEPROM byte into the endpoint */
330  				WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >> 1)));
331  
332  				/* Increment the address counter after use */
333  				CurrAddress += 2;
334  			}
335  		}
336  	}
337  	else
338  	{
339  		uint32_t PageStartAddress = CurrAddress;
340  
341  		if (MemoryType == 'F')
342  		{
343  			boot_page_erase(PageStartAddress);
344  			boot_spm_busy_wait();
345  		}
346  
347  		while (BlockSize--)
348  		{
349  			if (MemoryType == 'F')
350  			{
351  				/* If both bytes in current word have been written, increment the address counter */
352  				if (HighByte)
353  				{
354  					/* Write the next FLASH word to the current FLASH page */
355  					boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) | LowByte));
356  
357  					/* Increment the address counter after use */
358  					CurrAddress += 2;
359  				}
360  				else
361  				{
362  					LowByte = FetchNextCommandByte();
363  				}
364  				
365  				HighByte = !HighByte;
366  			}
367  			else
368  			{
369  				/* Write the next EEPROM byte from the endpoint */
370  				eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
371  
372  				/* Increment the address counter after use */
373  				CurrAddress += 2;
374  			}
375  		}
376  
377  		/* If in FLASH programming mode, commit the page after writing */
378  		if (MemoryType == 'F')
379  		{
380  			/* Commit the flash page to memory */
381  			boot_page_write(PageStartAddress);
382  
383  			/* Wait until write operation has completed */
384  			boot_spm_busy_wait();
385  		}
386  
387  		/* Send response byte back to the host */
388  		WriteNextResponseByte('\r');
389  	}
390  
391  	/* Re-enable timer 1 interrupt disabled earlier in this routine */	
392  	TIMSK1 = (1 << OCIE1A);
393  }
394  #endif
395  
396  /** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed
397   *  to allow reception of the next data packet from the host.
398   *
399   *  \return Next received byte from the host in the CDC data OUT endpoint
400   */
401  static uint8_t FetchNextCommandByte(void)
402  {
403  	/* Select the OUT endpoint so that the next data byte can be read */
404  	Endpoint_SelectEndpoint(CDC_RX_EPNUM);
405  
406  	/* If OUT endpoint empty, clear it and wait for the next packet from the host */
407  	while (!(Endpoint_IsReadWriteAllowed()))
408  	{
409  		Endpoint_ClearOUT();
410  
411  		while (!(Endpoint_IsOUTReceived()))
412  		{
413  			if (USB_DeviceState == DEVICE_STATE_Unattached)
414  			  return 0;
415  		}
416  	}
417  
418  	/* Fetch the next byte from the OUT endpoint */
419  	return Endpoint_Read_8();
420  }
421  
422  /** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free up the
423   *  bank when full ready for the next byte in the packet to the host.
424   *
425   *  \param[in] Response  Next response byte to send to the host
426   */
427  static void WriteNextResponseByte(const uint8_t Response)
428  {
429  	/* Select the IN endpoint so that the next data byte can be written */
430  	Endpoint_SelectEndpoint(CDC_TX_EPNUM);
431  
432  	/* If IN endpoint full, clear it and wait until ready for the next packet to the host */
433  	if (!(Endpoint_IsReadWriteAllowed()))
434  	{
435  		Endpoint_ClearIN();
436  
437  		while (!(Endpoint_IsINReady()))
438  		{
439  			if (USB_DeviceState == DEVICE_STATE_Unattached)
440  			  return;
441  		}
442  	}
443  
444  	/* Write the next byte to the IN endpoint */
445  	Endpoint_Write_8(Response);
446  	
447  	TX_LED_ON();
448  	TxLEDPulse = TX_RX_LED_PULSE_PERIOD;
449  }
450  
451  #define STK_OK              0x10
452  #define STK_INSYNC          0x14  // ' '
453  #define CRC_EOP             0x20  // 'SPACE'
454  #define STK_GET_SYNC        0x30  // '0'
455  
456  #define STK_GET_PARAMETER   0x41  // 'A'
457  #define STK_SET_DEVICE      0x42  // 'B'
458  #define STK_SET_DEVICE_EXT  0x45  // 'E'
459  #define STK_LOAD_ADDRESS    0x55  // 'U'
460  #define STK_UNIVERSAL       0x56  // 'V'
461  #define STK_PROG_PAGE       0x64  // 'd'
462  #define STK_READ_PAGE       0x74  // 't'
463  #define STK_READ_SIGN       0x75  // 'u'
464  
465  /** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required actions
466   *  and send the appropriate response back to the host.
467   */
468  void CDC_Task(void)
469  {
470  	/* Select the OUT endpoint */
471  	Endpoint_SelectEndpoint(CDC_RX_EPNUM);
472  
473  	/* Check if endpoint has a command in it sent from the host */
474  	if (!(Endpoint_IsOUTReceived()))
475  	  return;
476  	  
477  	RX_LED_ON();
478  	RxLEDPulse = TX_RX_LED_PULSE_PERIOD;
479  
480  	/* Read in the bootloader command (first byte sent from host) */
481  	uint8_t Command = FetchNextCommandByte();
482  
483  	if (Command == 'E')
484  	{
485  		/* We nearly run out the bootloader timeout clock, 
486  		* leaving just a few hundred milliseconds so the 
487  		* bootloder has time to respond and service any 
488  		* subsequent requests */
489  		Timeout = TIMEOUT_PERIOD - 500;
490  	
491  		/* Re-enable RWW section - must be done here in case 
492  		 * user has disabled verification on upload.  */
493  		boot_rww_enable_safe();		
494  
495  		// Send confirmation byte back to the host 
496  		WriteNextResponseByte('\r');
497  	}
498  	else if (Command == 'T')
499  	{
500  		FetchNextCommandByte();
501  
502  		// Send confirmation byte back to the host 
503  		WriteNextResponseByte('\r');
504  	}
505  	else if ((Command == 'L') || (Command == 'P'))
506  	{
507  		// Send confirmation byte back to the host 
508  		WriteNextResponseByte('\r');
509  	}
510  	else if (Command == 't')
511  	{
512  		// Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader 
513  		WriteNextResponseByte(0x44);
514  		WriteNextResponseByte(0x00);
515  	}
516  	else if (Command == 'a')
517  	{
518  		// Indicate auto-address increment is supported 
519  		WriteNextResponseByte('Y');
520  	}
521  	else if (Command == 'A')
522  	{
523  		// Set the current address to that given by the host 
524  		CurrAddress   = (FetchNextCommandByte() << 9);
525  		CurrAddress  |= (FetchNextCommandByte() << 1);
526  
527  		// Send confirmation byte back to the host 
528  		WriteNextResponseByte('\r');
529  	}
530  	else if (Command == 'p')
531  	{
532  		// Indicate serial programmer back to the host 
533  		WriteNextResponseByte('S');
534  	}
535  	else if (Command == 'S')
536  	{
537  		// Write the 7-byte software identifier to the endpoint 
538  		for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
539  		  WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
540  	}
541  	else if (Command == 'V')
542  	{
543  		WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
544  		WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
545  	}
546  	else if (Command == 's')
547  	{
548  		WriteNextResponseByte(AVR_SIGNATURE_3);
549  		WriteNextResponseByte(AVR_SIGNATURE_2);
550  		WriteNextResponseByte(AVR_SIGNATURE_1);
551  	}
552  	else if (Command == 'e')
553  	{
554  		// Clear the application section of flash 
555  		for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress += SPM_PAGESIZE)
556  		{
557  			boot_page_erase(CurrFlashAddress);
558  			boot_spm_busy_wait();
559  			boot_page_write(CurrFlashAddress);
560  			boot_spm_busy_wait();
561  		}
562  
563  		// Send confirmation byte back to the host 
564  		WriteNextResponseByte('\r');
565  	}
566  	#if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
567  	else if (Command == 'l')
568  	{
569  		// Set the lock bits to those given by the host 
570  		boot_lock_bits_set(FetchNextCommandByte());
571  
572  		// Send confirmation byte back to the host 
573  		WriteNextResponseByte('\r');
574  	}
575  	#endif
576  	else if (Command == 'r')
577  	{
578  		WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
579  	}
580  	else if (Command == 'F')
581  	{
582  		WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
583  	}
584  	else if (Command == 'N')
585  	{
586  		WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
587  	}
588  	else if (Command == 'Q')
589  	{
590  		WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
591  	}
592  	#if !defined(NO_BLOCK_SUPPORT)
593  	else if (Command == 'b')
594  	{
595  		WriteNextResponseByte('Y');
596  
597  		// Send block size to the host 
598  		WriteNextResponseByte(SPM_PAGESIZE >> 8);
599  		WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
600  	}
601  	else if ((Command == 'B') || (Command == 'g'))
602  	{
603  		// Keep resetting the timeout counter if we're receiving self-programming instructions
604  		Timeout = 0;
605  		// Delegate the block write/read to a separate function for clarity 
606  		ReadWriteMemoryBlock(Command);
607  	}
608  	#endif
609  	#if !defined(NO_FLASH_BYTE_SUPPORT)
610  	else if (Command == 'C')
611  	{
612  		// Write the high byte to the current flash page
613  		boot_page_fill(CurrAddress, FetchNextCommandByte());
614  
615  		// Send confirmation byte back to the host 
616  		WriteNextResponseByte('\r');
617  	}
618  	else if (Command == 'c')
619  	{
620  		// Write the low byte to the current flash page 
621  		boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
622  
623  		// Increment the address 
624  		CurrAddress += 2;
625  
626  		// Send confirmation byte back to the host 
627  		WriteNextResponseByte('\r');
628  	}
629  	else if (Command == 'm')
630  	{
631  		// Commit the flash page to memory
632  		boot_page_write(CurrAddress);
633  
634  		// Wait until write operation has completed 
635  		boot_spm_busy_wait();
636  
637  		// Send confirmation byte back to the host 
638  		WriteNextResponseByte('\r');
639  	}
640  	else if (Command == 'R')
641  	{
642  		#if (FLASHEND > 0xFFFF)
643  		uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
644  		#else
645  		uint16_t ProgramWord = pgm_read_word(CurrAddress);
646  		#endif
647  
648  		WriteNextResponseByte(ProgramWord >> 8);
649  		WriteNextResponseByte(ProgramWord & 0xFF);
650  	}
651  	#endif
652  	#if !defined(NO_EEPROM_BYTE_SUPPORT)
653  	else if (Command == 'D')
654  	{
655  		// Read the byte from the endpoint and write it to the EEPROM 
656  		eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
657  
658  		// Increment the address after use
659  		CurrAddress += 2;
660  
661  		// Send confirmation byte back to the host 
662  		WriteNextResponseByte('\r');
663  	}
664  	else if (Command == 'd')
665  	{
666  		// Read the EEPROM byte and write it to the endpoint 
667  		WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
668  
669  		// Increment the address after use 
670  		CurrAddress += 2;
671  	}
672  	#endif
673  	else if (Command != 27)
674  	{
675  		// Unknown (non-sync) command, return fail code 
676  		WriteNextResponseByte('?');
677  	}
678  	
679  
680  	/* Select the IN endpoint */
681  	Endpoint_SelectEndpoint(CDC_TX_EPNUM);
682  
683  	/* Remember if the endpoint is completely full before clearing it */
684  	bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
685  
686  	/* Send the endpoint data to the host */
687  	Endpoint_ClearIN();
688  
689  	/* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */
690  	if (IsEndpointFull)
691  	{
692  		while (!(Endpoint_IsINReady()))
693  		{
694  			if (USB_DeviceState == DEVICE_STATE_Unattached)
695  			  return;
696  		}
697  
698  		Endpoint_ClearIN();
699  	}
700  
701  	/* Wait until the data has been sent to the host */
702  	while (!(Endpoint_IsINReady()))
703  	{
704  		if (USB_DeviceState == DEVICE_STATE_Unattached)
705  		  return;
706  	}
707  
708  	/* Select the OUT endpoint */
709  	Endpoint_SelectEndpoint(CDC_RX_EPNUM);
710  
711  	/* Acknowledge the command from the host */
712  	Endpoint_ClearOUT();
713  }
714