copied over all of the custom pcb stuff and switched connectors + added PWM headers to the power board

git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4029 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/gyro_board/src/usb/CAN.c b/gyro_board/src/usb/CAN.c
new file mode 100644
index 0000000..74e0a62
--- /dev/null
+++ b/gyro_board/src/usb/CAN.c
@@ -0,0 +1,283 @@
+/* Standard includes. */
+#include "stdio.h"
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "task.h"
+
+/* Demo app includes. */
+#include "flash.h"
+#include "partest.h"
+#include "analog.h"
+#include "spi.h"
+#include "LPCUSB/usbapi.h"
+#include "CAN.h"
+
+static xQueueHandle CAN_tx_queue = NULL, CAN_rx_queue = NULL;
+
+/** Send a CAN message.  The message is stored by copy.
+ *
+ * \returns Zero on success, and one on failure to queue the message.
+ */
+int CAN_send(can_message *message) {
+  uint32_t sr = CAN1->SR;
+  // Queue the message up in a queue!
+  if (sr & 0x00040404) {
+    uint32_t IFx = (message->RTR << 30) +
+                   (message->length << 16) +
+                   (message->priority);
+
+    uint32_t data0 = message->wdata[0];
+    uint32_t data1 = message->wdata[1];
+
+    if(sr & 0x00000004){
+      CAN1->TFI1 = IFx;
+      CAN1->TID1 = message->id;
+      CAN1->TDA1 = data0; 
+      CAN1->TDB1 = data1;
+      CAN1->CMR = 0x00000021;
+      printf("Writing 1\n");
+      return 0;
+    } else if(sr & 0x00000400) {
+      CAN1->TFI2 = IFx;
+      CAN1->TID2 = message->id;
+      CAN1->TDA2 = data0; 
+      CAN1->TDB2 = data1;
+      CAN1->CMR = 0x00000041;
+      return 0;
+    } else if(sr & 0x00040000) {
+      CAN1->TFI3 = IFx;
+      CAN1->TID3 = message->id;
+      CAN1->TDA3 = data0; 
+      CAN1->TDB3 = data1;
+      CAN1->CMR = 0x00000081;
+      return 0;
+    }
+    return 1;
+  }
+  return xQueueSend(CAN_tx_queue, message, 0) != pdPASS;
+}
+
+/**
+ * Get a CAN message, blocking if one isn't available.
+ * This is useful for a read/dispatch thread.
+ *
+ * \returns 0 on Success, and nonzero on failure
+ */
+int CAN_get(can_message *message) {
+  // Blocking read the queue.
+  if (xQueueReceive(CAN_rx_queue, message, portMAX_DELAY) == pdFALSE) {
+    return 1;
+  } else {
+    return message->error;
+  }
+}
+
+void CAN_IRQHandler(void) {
+  uint32_t interrupts = CAN1->ICR;
+  long lHigherPriorityTaskWoken = pdFALSE;
+  can_message message;
+  // CAN1->CMR contains all the action items, like initiating a send et all.
+  // On a bus error interrupt, set an error semaphore so the handler can set the LED, or set it ourselfs.
+  printf("CAN interrupt\n");
+
+  if (interrupts & 0x1) {
+    // Recieved a packet.
+    uint32_t rfs = CAN1->RFS;
+
+    message.RTR = (rfs & 0x40000000) >> 30;
+    message.length = (rfs & 0x000f0000) >> 16;
+    message.id = CAN1->RID & 0x000007ff;
+
+    message.wdata[0] = CAN1->RDA;
+    message.wdata[1] = CAN1->RDB;
+
+    // Release the registers
+    CAN1->CMR = 0x00000004;
+
+    message.error = 0;
+
+    xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+    portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+    return;
+  }
+
+  if (interrupts & 0x602) {
+    // TX buffers are no longer empty (now empty??)
+    if (xQueueReceiveFromISR(CAN_tx_queue, &message, &lHigherPriorityTaskWoken)) {
+      uint32_t IFx = (message.RTR << 30) +
+                     (message.length << 16) +
+                     (message.priority);
+      uint32_t data0 = message.wdata[0];
+      uint32_t data1 = message.wdata[1];
+
+      // Message was in the queue, and will now be sent.
+      if (interrupts & 0x2) {
+        // TX buffer 1 is no longer empty
+        CAN1->TFI1 = IFx;
+        CAN1->TID1 = message.id;
+        CAN1->TDA1 = data0; 
+        CAN1->TDB1 = data1;
+        CAN1->CMR = 0x00000021;
+      } else if (interrupts & 0x200) {
+        // TX buffer 2 is no longer empty
+        CAN1->TFI2 = IFx;
+        CAN1->TID2 = message.id;
+        CAN1->TDA2 = data0; 
+        CAN1->TDB2 = data1;
+        CAN1->CMR = 0x00000041;
+      } else if (interrupts & 0x400) {
+        // TX buffer 3 is no longer empty
+        CAN1->TFI3 = IFx;
+        CAN1->TID3 = message.id;
+        CAN1->TDA3 = data0; 
+        CAN1->TDB3 = data1;
+        CAN1->CMR = 0x00000081;
+      }
+    }
+    portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+    return;
+  }
+
+  if (interrupts & 0x4) {
+    // Error Warning interrupt
+    message.error = 0x01;
+    if (CAN1->GSR & 0x00000040) {
+      // Reached the limit.
+      message.error = 0x01;
+    } else if (CAN1->GSR & 0x00000080) {
+      // No longer allowed to send.
+      message.error = 0x20;
+    } else {
+      message.error = 0x20;
+    }
+    xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+    portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+    return;
+  }
+
+  if (interrupts & 0x8) {
+    // Data overrun
+    CAN1->CMR = 0x00000008;
+    message.error = 0x02;
+    xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+    portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+    return;
+  }
+
+  if (interrupts & 0x20) {
+    // Error Passive Interrupt
+    message.error = 0x04;
+    xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+    portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+    return;
+  }
+
+  if (interrupts & 0x80) {
+    // Bus Error Interrupt
+    message.error = 0x08;
+    xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+    portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+    return;
+  }
+  message.error = 0x10;
+  xQueueSendFromISR(CAN_rx_queue, &message, &lHigherPriorityTaskWoken);
+  portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+}
+
+extern int VCOM_getchar(void);
+
+static portTASK_FUNCTION(vCAN1Write, pvParameters) {
+  can_message message;
+  message.RTR = 0;
+  message.id = 12;
+  message.priority = 1;
+  message.length = 4;
+
+  // Enable the pins.
+  PINCON->PINSEL3 = (PINCON->PINSEL3 & 0xffc3cf3f) | 0x00141040;
+
+  portTickType xLastFlashTime;
+  xLastFlashTime = xTaskGetTickCount();
+
+  for (;;) {
+    printf("hello\n");
+
+    int c = VCOM_getchar();
+    while (c != -1) {
+      printf("hello\n");
+      int j = c;
+      printf("Sending data 0x%x\n", j);
+      message.data[0] = j++;
+      message.data[1] = j++;
+      message.data[2] = j++;
+      message.data[3] = j;
+      CAN_send(&message);
+      c = VCOM_getchar();
+    }
+
+    vTaskDelayUntil(&xLastFlashTime, 500);
+  }
+}
+static portTASK_FUNCTION(vCAN1, pvParameters) {
+  portTickType xLastFlashTime;
+
+  CAN_rx_queue = xQueueCreate(20, sizeof(can_message));
+  CAN_tx_queue = xQueueCreate(5, sizeof(char));
+
+  if ((CAN_rx_queue == NULL) || (CAN_tx_queue == NULL)) {
+    /* Not enough heap available to create the buffer queues, can't do
+     * anything so just delete ourselves.
+     */
+    vTaskDelete(NULL);
+  }
+
+  // Enable CAN
+  SC->PCONP |= PCONP_PCCAN1;
+
+  PINCON->PINSEL0 = (PINCON->PINSEL0 & 0xfffffff0) | 0x00000005;
+  PINCON->PINMODE0 = (PINCON->PINMODE0 & 0xfffffffc) | 0x00000001;
+
+  // Enable RX, TX, overrun, Bus Error,
+  // Error Passive/Active, and Error Warning Interupts.
+  NVIC_SetPriority(CAN_IRQn, configCAN_INTERRUPT_PRIORITY);
+  NVIC_EnableIRQ(CAN_IRQn);
+
+  CAN1->IER = 0x000006af;
+
+  // Priority depends on the TX priority register
+  CAN1->MOD = 0x00000008;
+
+  CAN1->CMR = 0x00000004;
+
+  CANAF->AFMR = 0x00000002;
+
+  // CAN clocks. (Defaults look fine)
+
+  /* We need to initialise xLastFlashTime prior to the first call to
+  vTaskDelayUntil(). */
+  xLastFlashTime = xTaskGetTickCount();
+
+  can_message message;
+
+  xTaskCreate(vCAN1Write, (signed char *) "CAN1wx", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 4, NULL);
+
+  for (;;) {
+    /* Delay for half the flash period then turn the LED on. */
+    if (CAN_get(&message)) {
+      printf("Message error 0x%x\n", message.error);
+    } else {
+      printf("Got a message with a length of %d\n", message.length);
+      printf("data[0] = 0x%x\n", message.data[0]);
+      printf("data[1] = 0x%x\n", message.data[1]);
+      printf("data[2] = 0x%x\n", message.data[2]);
+      printf("data[3] = 0x%x\n", message.data[3]);
+    }
+  }
+}
+
+
+void initCAN(void){
+  xTaskCreate(vCAN1, (signed char *) "CAN1rx", configMINIMAL_STACK_SIZE + 400, NULL, tskIDLE_PRIORITY + 1, NULL);
+}
diff --git a/gyro_board/src/usb/CAN.h b/gyro_board/src/usb/CAN.h
new file mode 100644
index 0000000..1ef39d5
--- /dev/null
+++ b/gyro_board/src/usb/CAN.h
@@ -0,0 +1,19 @@
+#ifndef _CAN_H_
+#define _CAN_H_
+
+typedef struct _can_message {
+  unsigned RTR:1;
+  unsigned error:7;
+  uint16_t id;
+  uint8_t priority;
+  uint8_t length;
+  union {
+    uint8_t data[8];
+    uint32_t wdata[2];
+  };
+} can_message;
+
+int CAN_get(can_message *message);
+void initCAN(void);
+
+#endif
diff --git a/gyro_board/src/usb/CommonDemoTasks/BlockQ.c b/gyro_board/src/usb/CommonDemoTasks/BlockQ.c
new file mode 100644
index 0000000..e05af05
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/BlockQ.c
@@ -0,0 +1,293 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*
+ * Creates six tasks that operate on three queues as follows:
+ *
+ * The first two tasks send and receive an incrementing number to/from a queue.
+ * One task acts as a producer and the other as the consumer.  The consumer is a
+ * higher priority than the producer and is set to block on queue reads.  The queue
+ * only has space for one item - as soon as the producer posts a message on the
+ * queue the consumer will unblock, pre-empt the producer, and remove the item.
+ *
+ * The second two tasks work the other way around.  Again the queue used only has
+ * enough space for one item.  This time the consumer has a lower priority than the
+ * producer.  The producer will try to post on the queue blocking when the queue is
+ * full.  When the consumer wakes it will remove the item from the queue, causing
+ * the producer to unblock, pre-empt the consumer, and immediately re-fill the
+ * queue.
+ *
+ * The last two tasks use the same queue producer and consumer functions.  This time the queue has
+ * enough space for lots of items and the tasks operate at the same priority.  The
+ * producer will execute, placing items into the queue.  The consumer will start
+ * executing when either the queue becomes full (causing the producer to block) or
+ * a context switch occurs (tasks of the same priority will time slice).
+ *
+ */
+
+/*
+
+Changes from V4.1.1
+
+	+ The second set of tasks were created the wrong way around.  This has been
+	  corrected.
+*/
+
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* Demo program include files. */
+#include "BlockQ.h"
+
+#define blckqSTACK_SIZE		configMINIMAL_STACK_SIZE
+#define blckqNUM_TASK_SETS	( 3 )
+
+/* Structure used to pass parameters to the blocking queue tasks. */
+typedef struct BLOCKING_QUEUE_PARAMETERS {
+	xQueueHandle xQueue;					/*< The queue to be used by the task. */
+	portTickType xBlockTime;				/*< The block time to use on queue reads/writes. */
+	volatile short *psCheckVariable;	/*< Incremented on each successful cycle to check the task is still running. */
+} xBlockingQueueParameters;
+
+/* Task function that creates an incrementing number and posts it on a queue. */
+static portTASK_FUNCTION_PROTO(vBlockingQueueProducer, pvParameters);
+
+/* Task function that removes the incrementing number from a queue and checks that
+it is the expected number. */
+static portTASK_FUNCTION_PROTO(vBlockingQueueConsumer, pvParameters);
+
+/* Variables which are incremented each time an item is removed from a queue, and
+found to be the expected value.
+These are used to check that the tasks are still running. */
+static volatile short sBlockingConsumerCount[ blckqNUM_TASK_SETS ] = {(unsigned short) 0, (unsigned short) 0, (unsigned short) 0 };
+
+/* Variable which are incremented each time an item is posted on a queue.   These
+are used to check that the tasks are still running. */
+static volatile short sBlockingProducerCount[ blckqNUM_TASK_SETS ] = {(unsigned short) 0, (unsigned short) 0, (unsigned short) 0 };
+
+/*-----------------------------------------------------------*/
+
+void vStartBlockingQueueTasks(unsigned portBASE_TYPE uxPriority)
+{
+	xBlockingQueueParameters *pxQueueParameters1, *pxQueueParameters2;
+	xBlockingQueueParameters *pxQueueParameters3, *pxQueueParameters4;
+	xBlockingQueueParameters *pxQueueParameters5, *pxQueueParameters6;
+	const unsigned portBASE_TYPE uxQueueSize1 = 1, uxQueueSize5 = 5;
+	const portTickType xBlockTime = (portTickType) 1000 / portTICK_RATE_MS;
+	const portTickType xDontBlock = (portTickType) 0;
+
+	/* Create the first two tasks as described at the top of the file. */
+
+	/* First create the structure used to pass parameters to the consumer tasks. */
+	pxQueueParameters1 = (xBlockingQueueParameters *) pvPortMalloc(sizeof(xBlockingQueueParameters));
+
+	/* Create the queue used by the first two tasks to pass the incrementing number.
+	Pass a pointer to the queue in the parameter structure. */
+	pxQueueParameters1->xQueue = xQueueCreate(uxQueueSize1, (unsigned portBASE_TYPE) sizeof(unsigned short));
+
+	/* The consumer is created first so gets a block time as described above. */
+	pxQueueParameters1->xBlockTime = xBlockTime;
+
+	/* Pass in the variable that this task is going to increment so we can check it
+	is still running. */
+	pxQueueParameters1->psCheckVariable = &(sBlockingConsumerCount[ 0 ]);
+
+	/* Create the structure used to pass parameters to the producer task. */
+	pxQueueParameters2 = (xBlockingQueueParameters *) pvPortMalloc(sizeof(xBlockingQueueParameters));
+
+	/* Pass the queue to this task also, using the parameter structure. */
+	pxQueueParameters2->xQueue = pxQueueParameters1->xQueue;
+
+	/* The producer is not going to block - as soon as it posts the consumer will
+	wake and remove the item so the producer should always have room to post. */
+	pxQueueParameters2->xBlockTime = xDontBlock;
+
+	/* Pass in the variable that this task is going to increment so we can check
+	it is still running. */
+	pxQueueParameters2->psCheckVariable = &(sBlockingProducerCount[ 0 ]);
+
+
+	/* Note the producer has a lower priority than the consumer when the tasks are
+	spawned. */
+	xTaskCreate(vBlockingQueueConsumer, (signed char *) "QConsB1", blckqSTACK_SIZE, (void *) pxQueueParameters1, uxPriority, NULL);
+	xTaskCreate(vBlockingQueueProducer, (signed char *) "QProdB2", blckqSTACK_SIZE, (void *) pxQueueParameters2, tskIDLE_PRIORITY, NULL);
+
+
+
+	/* Create the second two tasks as described at the top of the file.   This uses
+	the same mechanism but reverses the task priorities. */
+
+	pxQueueParameters3 = (xBlockingQueueParameters *) pvPortMalloc(sizeof(xBlockingQueueParameters));
+	pxQueueParameters3->xQueue = xQueueCreate(uxQueueSize1, (unsigned portBASE_TYPE) sizeof(unsigned short));
+	pxQueueParameters3->xBlockTime = xDontBlock;
+	pxQueueParameters3->psCheckVariable = &(sBlockingProducerCount[ 1 ]);
+
+	pxQueueParameters4 = (xBlockingQueueParameters *) pvPortMalloc(sizeof(xBlockingQueueParameters));
+	pxQueueParameters4->xQueue = pxQueueParameters3->xQueue;
+	pxQueueParameters4->xBlockTime = xBlockTime;
+	pxQueueParameters4->psCheckVariable = &(sBlockingConsumerCount[ 1 ]);
+
+	xTaskCreate(vBlockingQueueConsumer, (signed char *) "QProdB3", blckqSTACK_SIZE, (void *) pxQueueParameters3, tskIDLE_PRIORITY, NULL);
+	xTaskCreate(vBlockingQueueProducer, (signed char *) "QConsB4", blckqSTACK_SIZE, (void *) pxQueueParameters4, uxPriority, NULL);
+
+
+
+	/* Create the last two tasks as described above.  The mechanism is again just
+	the same.  This time both parameter structures are given a block time. */
+	pxQueueParameters5 = (xBlockingQueueParameters *) pvPortMalloc(sizeof(xBlockingQueueParameters));
+	pxQueueParameters5->xQueue = xQueueCreate(uxQueueSize5, (unsigned portBASE_TYPE) sizeof(unsigned short));
+	pxQueueParameters5->xBlockTime = xBlockTime;
+	pxQueueParameters5->psCheckVariable = &(sBlockingProducerCount[ 2 ]);
+
+	pxQueueParameters6 = (xBlockingQueueParameters *) pvPortMalloc(sizeof(xBlockingQueueParameters));
+	pxQueueParameters6->xQueue = pxQueueParameters5->xQueue;
+	pxQueueParameters6->xBlockTime = xBlockTime;
+	pxQueueParameters6->psCheckVariable = &(sBlockingConsumerCount[ 2 ]);
+
+	xTaskCreate(vBlockingQueueProducer, (signed char *) "QProdB5", blckqSTACK_SIZE, (void *) pxQueueParameters5, tskIDLE_PRIORITY, NULL);
+	xTaskCreate(vBlockingQueueConsumer, (signed char *) "QConsB6", blckqSTACK_SIZE, (void *) pxQueueParameters6, tskIDLE_PRIORITY, NULL);
+}
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION(vBlockingQueueProducer, pvParameters)
+{
+	unsigned short usValue = 0;
+	xBlockingQueueParameters *pxQueueParameters;
+	short sErrorEverOccurred = pdFALSE;
+
+	pxQueueParameters = (xBlockingQueueParameters *) pvParameters;
+
+	for (;;) {
+		if (xQueueSend(pxQueueParameters->xQueue, (void *) &usValue, pxQueueParameters->xBlockTime) != pdPASS) {
+			sErrorEverOccurred = pdTRUE;
+		} else {
+			/* We have successfully posted a message, so increment the variable
+			used to check we are still running. */
+			if (sErrorEverOccurred == pdFALSE) {
+				(*pxQueueParameters->psCheckVariable)++;
+			}
+
+			/* Increment the variable we are going to post next time round.  The
+			consumer will expect the numbers to	follow in numerical order. */
+			++usValue;
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION(vBlockingQueueConsumer, pvParameters)
+{
+	unsigned short usData, usExpectedValue = 0;
+	xBlockingQueueParameters *pxQueueParameters;
+	short sErrorEverOccurred = pdFALSE;
+
+	pxQueueParameters = (xBlockingQueueParameters *) pvParameters;
+
+	for (;;) {
+		if (xQueueReceive(pxQueueParameters->xQueue, &usData, pxQueueParameters->xBlockTime) == pdPASS) {
+			if (usData != usExpectedValue) {
+				/* Catch-up. */
+				usExpectedValue = usData;
+
+				sErrorEverOccurred = pdTRUE;
+			} else {
+				/* We have successfully received a message, so increment the
+				variable used to check we are still running. */
+				if (sErrorEverOccurred == pdFALSE) {
+					(*pxQueueParameters->psCheckVariable)++;
+				}
+
+				/* Increment the value we expect to remove from the queue next time
+				round. */
+				++usExpectedValue;
+			}
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreBlockingQueuesStillRunning(void)
+{
+	static short sLastBlockingConsumerCount[ blckqNUM_TASK_SETS ] = {(unsigned short) 0, (unsigned short) 0, (unsigned short) 0 };
+	static short sLastBlockingProducerCount[ blckqNUM_TASK_SETS ] = {(unsigned short) 0, (unsigned short) 0, (unsigned short) 0 };
+	portBASE_TYPE xReturn = pdPASS, xTasks;
+
+	/* Not too worried about mutual exclusion on these variables as they are 16
+	bits and we are only reading them. We also only care to see if they have
+	changed or not.
+
+	Loop through each check variable to and return pdFALSE if any are found not
+	to have changed since the last call. */
+
+	for (xTasks = 0; xTasks < blckqNUM_TASK_SETS; xTasks++) {
+		if (sBlockingConsumerCount[ xTasks ] == sLastBlockingConsumerCount[ xTasks ]) {
+			xReturn = pdFALSE;
+		}
+		sLastBlockingConsumerCount[ xTasks ] = sBlockingConsumerCount[ xTasks ];
+
+
+		if (sBlockingProducerCount[ xTasks ] == sLastBlockingProducerCount[ xTasks ]) {
+			xReturn = pdFALSE;
+		}
+		sLastBlockingProducerCount[ xTasks ] = sBlockingProducerCount[ xTasks ];
+	}
+
+	return xReturn;
+}
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/GenQTest.c b/gyro_board/src/usb/CommonDemoTasks/GenQTest.c
new file mode 100644
index 0000000..1b486ba
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/GenQTest.c
@@ -0,0 +1,525 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+/*
+ * Tests the extra queue functionality introduced in FreeRTOS.org V4.5.0 -
+ * including xQueueSendToFront(), xQueueSendToBack(), xQueuePeek() and
+ * mutex behaviour.
+ *
+ * See the comments above the prvSendFrontAndBackTest() and
+ * prvLowPriorityMutexTask() prototypes below for more information.
+ */
+
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* Demo program include files. */
+#include "GenQTest.h"
+
+#define genqQUEUE_LENGTH		( 5 )
+#define genqNO_BLOCK			( 0 )
+
+#define genqMUTEX_LOW_PRIORITY		( tskIDLE_PRIORITY )
+#define genqMUTEX_TEST_PRIORITY		( tskIDLE_PRIORITY + 1 )
+#define genqMUTEX_MEDIUM_PRIORITY	( tskIDLE_PRIORITY + 2 )
+#define genqMUTEX_HIGH_PRIORITY		( tskIDLE_PRIORITY + 3 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Tests the behaviour of the xQueueSendToFront() and xQueueSendToBack()
+ * macros by using both to fill a queue, then reading from the queue to
+ * check the resultant queue order is as expected.  Queue data is also
+ * peeked.
+ */
+static void prvSendFrontAndBackTest(void *pvParameters);
+
+/*
+ * The following three tasks are used to demonstrate the mutex behaviour.
+ * Each task is given a different priority to demonstrate the priority
+ * inheritance mechanism.
+ *
+ * The low priority task obtains a mutex.  After this a high priority task
+ * attempts to obtain the same mutex, causing its priority to be inherited
+ * by the low priority task.  The task with the inherited high priority then
+ * resumes a medium priority task to ensure it is not blocked by the medium
+ * priority task while it holds the inherited high priority.  Once the mutex
+ * is returned the task with the inherited priority returns to its original
+ * low priority, and is therefore immediately preempted by first the high
+ * priority task and then the medium prioroity task before it can continue.
+ */
+static void prvLowPriorityMutexTask(void *pvParameters);
+static void prvMediumPriorityMutexTask(void *pvParameters);
+static void prvHighPriorityMutexTask(void *pvParameters);
+
+/*-----------------------------------------------------------*/
+
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be
+detected in any of the tasks. */
+static portBASE_TYPE xErrorDetected = pdFALSE;
+
+/* Counters that are incremented on each cycle of a test.  This is used to
+detect a stalled task - a test that is no longer running. */
+static volatile unsigned portLONG ulLoopCounter = 0;
+static volatile unsigned portLONG ulLoopCounter2 = 0;
+
+/* The variable that is guarded by the mutex in the mutex demo tasks. */
+static volatile unsigned portLONG ulGuardedVariable = 0;
+
+/* Handles used in the mutext test to suspend and resume the high and medium
+priority mutex test tasks. */
+static xTaskHandle xHighPriorityMutexTask, xMediumPriorityMutexTask;
+
+/*-----------------------------------------------------------*/
+
+void vStartGenericQueueTasks(unsigned portBASE_TYPE uxPriority)
+{
+	xQueueHandle xQueue;
+	xSemaphoreHandle xMutex;
+
+	/* Create the queue that we are going to use for the
+	prvSendFrontAndBackTest demo. */
+	xQueue = xQueueCreate(genqQUEUE_LENGTH, sizeof(unsigned portLONG));
+
+	/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
+	in use.  The queue registry is provided as a means for kernel aware
+	debuggers to locate queues and has no purpose if a kernel aware debugger
+	is not being used.  The call to vQueueAddToRegistry() will be removed
+	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+	defined to be less than 1. */
+	vQueueAddToRegistry(xQueue, (signed portCHAR *) "Gen_Queue_Test");
+
+	/* Create the demo task and pass it the queue just created.  We are
+	passing the queue handle by value so it does not matter that it is
+	declared on the stack here. */
+	xTaskCreate(prvSendFrontAndBackTest, (signed portCHAR *)"GenQ", configMINIMAL_STACK_SIZE, (void *) xQueue, uxPriority, NULL);
+
+	/* Create the mutex used by the prvMutexTest task. */
+	xMutex = xSemaphoreCreateMutex();
+
+	/* vQueueAddToRegistry() adds the mutex to the registry, if one is
+	in use.  The registry is provided as a means for kernel aware
+	debuggers to locate mutexes and has no purpose if a kernel aware debugger
+	is not being used.  The call to vQueueAddToRegistry() will be removed
+	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+	defined to be less than 1. */
+	vQueueAddToRegistry((xQueueHandle) xMutex, (signed portCHAR *) "Gen_Queue_Mutex");
+
+	/* Create the mutex demo tasks and pass it the mutex just created.  We are
+	passing the mutex handle by value so it does not matter that it is declared
+	on the stack here. */
+	xTaskCreate(prvLowPriorityMutexTask, (signed portCHAR *)"MuLow", configMINIMAL_STACK_SIZE, (void *) xMutex, genqMUTEX_LOW_PRIORITY, NULL);
+	xTaskCreate(prvMediumPriorityMutexTask, (signed portCHAR *)"MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask);
+	xTaskCreate(prvHighPriorityMutexTask, (signed portCHAR *)"MuHigh", configMINIMAL_STACK_SIZE, (void *) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask);
+}
+/*-----------------------------------------------------------*/
+
+static void prvSendFrontAndBackTest(void *pvParameters)
+{
+	unsigned portLONG ulData, ulData2;
+	xQueueHandle xQueue;
+
+#ifdef USE_STDIO
+	void vPrintDisplayMessage(const portCHAR * const * ppcMessageToSend);
+
+	const portCHAR * const pcTaskStartMsg = "Queue SendToFront/SendToBack/Peek test started.\r\n";
+
+	/* Queue a message for printing to say the task has started. */
+	vPrintDisplayMessage(&pcTaskStartMsg);
+#endif
+
+	xQueue = (xQueueHandle) pvParameters;
+
+	for (;;) {
+		/* The queue is empty, so sending an item to the back of the queue
+		should have the same efect as sending it to the front of the queue.
+
+		First send to the front and check everything is as expected. */
+		xQueueSendToFront(xQueue, (void *) &ulLoopCounter, genqNO_BLOCK);
+
+		if (uxQueueMessagesWaiting(xQueue) != 1) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (xQueueReceive(xQueue, (void *) &ulData, genqNO_BLOCK) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* The data we sent to the queue should equal the data we just received
+		from the queue. */
+		if (ulLoopCounter != ulData) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Then do the same, sending the data to the back, checking everything
+		is as expected. */
+		if (uxQueueMessagesWaiting(xQueue) != 0) {
+			xErrorDetected = pdTRUE;
+		}
+
+		xQueueSendToBack(xQueue, (void *) &ulLoopCounter, genqNO_BLOCK);
+
+		if (uxQueueMessagesWaiting(xQueue) != 1) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (xQueueReceive(xQueue, (void *) &ulData, genqNO_BLOCK) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (uxQueueMessagesWaiting(xQueue) != 0) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* The data we sent to the queue should equal the data we just received
+		from the queue. */
+		if (ulLoopCounter != ulData) {
+			xErrorDetected = pdTRUE;
+		}
+
+#if configUSE_PREEMPTION == 0
+		taskYIELD();
+#endif
+
+
+
+		/* Place 2, 3, 4 into the queue, adding items to the back of the queue. */
+		for (ulData = 2; ulData < 5; ulData++) {
+			xQueueSendToBack(xQueue, (void *) &ulData, genqNO_BLOCK);
+		}
+
+		/* Now the order in the queue should be 2, 3, 4, with 2 being the first
+		thing to be read out.  Now add 1 then 0 to the front of the queue. */
+		if (uxQueueMessagesWaiting(xQueue) != 3) {
+			xErrorDetected = pdTRUE;
+		}
+		ulData = 1;
+		xQueueSendToFront(xQueue, (void *) &ulData, genqNO_BLOCK);
+		ulData = 0;
+		xQueueSendToFront(xQueue, (void *) &ulData, genqNO_BLOCK);
+
+		/* Now the queue should be full, and when we read the data out we
+		should receive 0, 1, 2, 3, 4. */
+		if (uxQueueMessagesWaiting(xQueue) != 5) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (xQueueSendToFront(xQueue, (void *) &ulData, genqNO_BLOCK) != errQUEUE_FULL) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (xQueueSendToBack(xQueue, (void *) &ulData, genqNO_BLOCK) != errQUEUE_FULL) {
+			xErrorDetected = pdTRUE;
+		}
+
+#if configUSE_PREEMPTION == 0
+		taskYIELD();
+#endif
+
+		/* Check the data we read out is in the expected order. */
+		for (ulData = 0; ulData < genqQUEUE_LENGTH; ulData++) {
+			/* Try peeking the data first. */
+			if (xQueuePeek(xQueue, &ulData2, genqNO_BLOCK) != pdPASS) {
+				xErrorDetected = pdTRUE;
+			}
+
+			if (ulData != ulData2) {
+				xErrorDetected = pdTRUE;
+			}
+
+
+			/* Now try receiving the data for real.  The value should be the
+			same.  Clobber the value first so we know we really received it. */
+			ulData2 = ~ulData2;
+			if (xQueueReceive(xQueue, &ulData2, genqNO_BLOCK) != pdPASS) {
+				xErrorDetected = pdTRUE;
+			}
+
+			if (ulData != ulData2) {
+				xErrorDetected = pdTRUE;
+			}
+		}
+
+		/* The queue should now be empty again. */
+		if (uxQueueMessagesWaiting(xQueue) != 0) {
+			xErrorDetected = pdTRUE;
+		}
+
+#if configUSE_PREEMPTION == 0
+		taskYIELD();
+#endif
+
+
+		/* Our queue is empty once more, add 10, 11 to the back. */
+		ulData = 10;
+		if (xQueueSend(xQueue, &ulData, genqNO_BLOCK) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+		ulData = 11;
+		if (xQueueSend(xQueue, &ulData, genqNO_BLOCK) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (uxQueueMessagesWaiting(xQueue) != 2) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Now we should have 10, 11 in the queue.  Add 7, 8, 9 to the
+		front. */
+		for (ulData = 9; ulData >= 7; ulData--) {
+			if (xQueueSendToFront(xQueue, (void *) &ulData, genqNO_BLOCK) != pdPASS) {
+				xErrorDetected = pdTRUE;
+			}
+		}
+
+		/* Now check that the queue is full, and that receiving data provides
+		the expected sequence of 7, 8, 9, 10, 11. */
+		if (uxQueueMessagesWaiting(xQueue) != 5) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (xQueueSendToFront(xQueue, (void *) &ulData, genqNO_BLOCK) != errQUEUE_FULL) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (xQueueSendToBack(xQueue, (void *) &ulData, genqNO_BLOCK) != errQUEUE_FULL) {
+			xErrorDetected = pdTRUE;
+		}
+
+#if configUSE_PREEMPTION == 0
+		taskYIELD();
+#endif
+
+		/* Check the data we read out is in the expected order. */
+		for (ulData = 7; ulData < (7 + genqQUEUE_LENGTH); ulData++) {
+			if (xQueueReceive(xQueue, &ulData2, genqNO_BLOCK) != pdPASS) {
+				xErrorDetected = pdTRUE;
+			}
+
+			if (ulData != ulData2) {
+				xErrorDetected = pdTRUE;
+			}
+		}
+
+		if (uxQueueMessagesWaiting(xQueue) != 0) {
+			xErrorDetected = pdTRUE;
+		}
+
+		ulLoopCounter++;
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvLowPriorityMutexTask(void *pvParameters)
+{
+	xSemaphoreHandle xMutex = (xSemaphoreHandle) pvParameters;
+
+#ifdef USE_STDIO
+	void vPrintDisplayMessage(const portCHAR * const * ppcMessageToSend);
+
+	const portCHAR * const pcTaskStartMsg = "Mutex with priority inheritance test started.\r\n";
+
+	/* Queue a message for printing to say the task has started. */
+	vPrintDisplayMessage(&pcTaskStartMsg);
+#endif
+
+	for (;;) {
+		/* Take the mutex.  It should be available now. */
+		if (xSemaphoreTake(xMutex, genqNO_BLOCK) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Set our guarded variable to a known start value. */
+		ulGuardedVariable = 0;
+
+		/* Our priority should be as per that assigned when the task was
+		created. */
+		if (uxTaskPriorityGet(NULL) != genqMUTEX_LOW_PRIORITY) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Now unsuspend the high priority task.  This will attempt to take the
+		mutex, and block when it finds it cannot obtain it. */
+		vTaskResume(xHighPriorityMutexTask);
+
+		/* We should now have inherited the prioritoy of the high priority task,
+		as by now it will have attempted to get the mutex. */
+		if (uxTaskPriorityGet(NULL) != genqMUTEX_HIGH_PRIORITY) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* We can attempt to set our priority to the test priority - between the
+		idle priority and the medium/high test priorities, but our actual
+		prioroity should remain at the high priority. */
+		vTaskPrioritySet(NULL, genqMUTEX_TEST_PRIORITY);
+		if (uxTaskPriorityGet(NULL) != genqMUTEX_HIGH_PRIORITY) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Now unsuspend the medium priority task.  This should not run as our
+		inherited priority is above that of the medium priority task. */
+		vTaskResume(xMediumPriorityMutexTask);
+
+		/* If the did run then it will have incremented our guarded variable. */
+		if (ulGuardedVariable != 0) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* When we give back the semaphore our priority should be disinherited
+		back to the priority to which we attempted to set ourselves.  This means
+		that when the high priority task next blocks, the medium priority task
+		should execute and increment the guarded variable.   When we next run
+		both the high and medium priority tasks will have been suspended again. */
+		if (xSemaphoreGive(xMutex) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Check that the guarded variable did indeed increment... */
+		if (ulGuardedVariable != 1) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* ... and that our priority has been disinherited to
+		genqMUTEX_TEST_PRIORITY. */
+		if (uxTaskPriorityGet(NULL) != genqMUTEX_TEST_PRIORITY) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Set our priority back to our original priority ready for the next
+		loop around this test. */
+		vTaskPrioritySet(NULL, genqMUTEX_LOW_PRIORITY);
+
+		/* Just to show we are still running. */
+		ulLoopCounter2++;
+
+#if configUSE_PREEMPTION == 0
+		taskYIELD();
+#endif
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvMediumPriorityMutexTask(void *pvParameters)
+{
+	(void) pvParameters;
+
+	for (;;) {
+		/* The medium priority task starts by suspending itself.  The low
+		priority task will unsuspend this task when required. */
+		vTaskSuspend(NULL);
+
+		/* When this task unsuspends all it does is increment the guarded
+		variable, this is so the low priority task knows that it has
+		executed. */
+		ulGuardedVariable++;
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvHighPriorityMutexTask(void *pvParameters)
+{
+	xSemaphoreHandle xMutex = (xSemaphoreHandle) pvParameters;
+
+	for (;;) {
+		/* The high priority task starts by suspending itself.  The low
+		priority task will unsuspend this task when required. */
+		vTaskSuspend(NULL);
+
+		/* When this task unsuspends all it does is attempt to obtain
+		the mutex.  It should find the mutex is not available so a
+		block time is specified. */
+		if (xSemaphoreTake(xMutex, portMAX_DELAY) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* When we eventually obtain the mutex we just give it back then
+		return to suspend ready for the next test. */
+		if (xSemaphoreGive(xMutex) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreGenericQueueTasksStillRunning(void)
+{
+	static unsigned portLONG ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
+
+	/* If the demo task is still running then we expect the loopcounters to
+	have incremented since this function was last called. */
+	if (ulLastLoopCounter == ulLoopCounter) {
+		xErrorDetected = pdTRUE;
+	}
+
+	if (ulLastLoopCounter2 == ulLoopCounter2) {
+		xErrorDetected = pdTRUE;
+	}
+
+	ulLastLoopCounter = ulLoopCounter;
+	ulLastLoopCounter2 = ulLoopCounter2;
+
+	/* Errors detected in the task itself will have latched xErrorDetected
+	to true. */
+
+	return !xErrorDetected;
+}
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/PollQ.c b/gyro_board/src/usb/CommonDemoTasks/PollQ.c
new file mode 100644
index 0000000..5428693
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/PollQ.c
@@ -0,0 +1,230 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*
+ * This version of PollQ. c is for use on systems that have limited stack
+ * space and no display facilities.  The complete version can be found in
+ * the Demo/Common/Full directory.
+ *
+ * Creates two tasks that communicate over a single queue.  One task acts as a
+ * producer, the other a consumer.
+ *
+ * The producer loops for three iteration, posting an incrementing number onto the
+ * queue each cycle.  It then delays for a fixed period before doing exactly the
+ * same again.
+ *
+ * The consumer loops emptying the queue.  Each item removed from the queue is
+ * checked to ensure it contains the expected value.  When the queue is empty it
+ * blocks for a fixed period, then does the same again.
+ *
+ * All queue access is performed without blocking.  The consumer completely empties
+ * the queue each time it runs so the producer should never find the queue full.
+ *
+ * An error is flagged if the consumer obtains an unexpected value or the producer
+ * find the queue is full.
+ */
+
+/*
+Changes from V2.0.0
+
+	+ Delay periods are now specified using variables and constants of
+	  portTickType rather than unsigned long.
+*/
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* Demo program include files. */
+#include "PollQ.h"
+
+#define pollqSTACK_SIZE			configMINIMAL_STACK_SIZE
+#define pollqQUEUE_SIZE			( 10 )
+#define pollqPRODUCER_DELAY		( ( portTickType ) 200 / portTICK_RATE_MS )
+#define pollqCONSUMER_DELAY		( pollqPRODUCER_DELAY - ( portTickType ) ( 20 / portTICK_RATE_MS ) )
+#define pollqNO_DELAY			( ( portTickType ) 0 )
+#define pollqVALUES_TO_PRODUCE	( ( signed portBASE_TYPE ) 3 )
+#define pollqINITIAL_VALUE		( ( signed portBASE_TYPE ) 0 )
+
+/* The task that posts the incrementing number onto the queue. */
+static portTASK_FUNCTION_PROTO(vPolledQueueProducer, pvParameters);
+
+/* The task that empties the queue. */
+static portTASK_FUNCTION_PROTO(vPolledQueueConsumer, pvParameters);
+
+/* Variables that are used to check that the tasks are still running with no
+errors. */
+static volatile signed portBASE_TYPE xPollingConsumerCount = pollqINITIAL_VALUE, xPollingProducerCount = pollqINITIAL_VALUE;
+
+/*-----------------------------------------------------------*/
+
+void vStartPolledQueueTasks(unsigned portBASE_TYPE uxPriority)
+{
+	static xQueueHandle xPolledQueue;
+
+	/* Create the queue used by the producer and consumer. */
+	xPolledQueue = xQueueCreate(pollqQUEUE_SIZE, (unsigned portBASE_TYPE) sizeof(unsigned short));
+
+	/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
+	in use.  The queue registry is provided as a means for kernel aware
+	debuggers to locate queues and has no purpose if a kernel aware debugger
+	is not being used.  The call to vQueueAddToRegistry() will be removed
+	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+	defined to be less than 1. */
+	vQueueAddToRegistry(xPolledQueue, (signed char *) "Poll_Test_Queue");
+
+	/* Spawn the producer and consumer. */
+	xTaskCreate(vPolledQueueConsumer, (signed char *) "QConsNB", pollqSTACK_SIZE, (void *) &xPolledQueue, uxPriority, (xTaskHandle *) NULL);
+	xTaskCreate(vPolledQueueProducer, (signed char *) "QProdNB", pollqSTACK_SIZE, (void *) &xPolledQueue, uxPriority, (xTaskHandle *) NULL);
+}
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION(vPolledQueueProducer, pvParameters)
+{
+	unsigned short usValue = (unsigned short) 0;
+	signed portBASE_TYPE xError = pdFALSE, xLoop;
+
+	for (;;) {
+		for (xLoop = 0; xLoop < pollqVALUES_TO_PRODUCE; xLoop++) {
+			/* Send an incrementing number on the queue without blocking. */
+			if (xQueueSend(*((xQueueHandle *) pvParameters), (void *) &usValue, pollqNO_DELAY) != pdPASS) {
+				/* We should never find the queue full so if we get here there
+				has been an error. */
+				xError = pdTRUE;
+			} else {
+				if (xError == pdFALSE) {
+					/* If an error has ever been recorded we stop incrementing the
+					check variable. */
+					portENTER_CRITICAL();
+					xPollingProducerCount++;
+					portEXIT_CRITICAL();
+				}
+
+				/* Update the value we are going to post next time around. */
+				usValue++;
+			}
+		}
+
+		/* Wait before we start posting again to ensure the consumer runs and
+		empties the queue. */
+		vTaskDelay(pollqPRODUCER_DELAY);
+	}
+}  /*lint !e818 Function prototype must conform to API. */
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION(vPolledQueueConsumer, pvParameters)
+{
+	unsigned short usData, usExpectedValue = (unsigned short) 0;
+	signed portBASE_TYPE xError = pdFALSE;
+
+	for (;;) {
+		/* Loop until the queue is empty. */
+		while (uxQueueMessagesWaiting(*((xQueueHandle *) pvParameters))) {
+			if (xQueueReceive(*((xQueueHandle *) pvParameters), &usData, pollqNO_DELAY) == pdPASS) {
+				if (usData != usExpectedValue) {
+					/* This is not what we expected to receive so an error has
+					occurred. */
+					xError = pdTRUE;
+
+					/* Catch-up to the value we received so our next expected
+					value should again be correct. */
+					usExpectedValue = usData;
+				} else {
+					if (xError == pdFALSE) {
+						/* Only increment the check variable if no errors have
+						occurred. */
+						portENTER_CRITICAL();
+						xPollingConsumerCount++;
+						portEXIT_CRITICAL();
+					}
+				}
+
+				/* Next time round we would expect the number to be one higher. */
+				usExpectedValue++;
+			}
+		}
+
+		/* Now the queue is empty we block, allowing the producer to place more
+		items in the queue. */
+		vTaskDelay(pollqCONSUMER_DELAY);
+	}
+} /*lint !e818 Function prototype must conform to API. */
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running with no errors. */
+portBASE_TYPE xArePollingQueuesStillRunning(void)
+{
+	portBASE_TYPE xReturn;
+
+	/* Check both the consumer and producer poll count to check they have both
+	been changed since out last trip round.  We do not need a critical section
+	around the check variables as this is called from a higher priority than
+	the other tasks that access the same variables. */
+	if ((xPollingConsumerCount == pollqINITIAL_VALUE) ||
+	                (xPollingProducerCount == pollqINITIAL_VALUE)
+	   ) {
+		xReturn = pdFALSE;
+	} else {
+		xReturn = pdTRUE;
+	}
+
+	/* Set the check variables back down so we know if they have been
+	incremented the next time around. */
+	xPollingConsumerCount = pollqINITIAL_VALUE;
+	xPollingProducerCount = pollqINITIAL_VALUE;
+
+	return xReturn;
+}
diff --git a/gyro_board/src/usb/CommonDemoTasks/QPeek.c b/gyro_board/src/usb/CommonDemoTasks/QPeek.c
new file mode 100644
index 0000000..6aa2f78
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/QPeek.c
@@ -0,0 +1,416 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+/*
+ * Tests the behaviour when data is peeked from a queue when there are
+ * multiple tasks blocked on the queue.
+ */
+
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+/* Demo program include files. */
+#include "QPeek.h"
+
+#define qpeekQUEUE_LENGTH		( 5 )
+#define qpeekNO_BLOCK			( 0 )
+#define qpeekSHORT_DELAY		( 10 )
+
+#define qpeekLOW_PRIORITY			( tskIDLE_PRIORITY + 0 )
+#define qpeekMEDIUM_PRIORITY		( tskIDLE_PRIORITY + 1 )
+#define qpeekHIGH_PRIORITY			( tskIDLE_PRIORITY + 2 )
+#define qpeekHIGHEST_PRIORITY		( tskIDLE_PRIORITY + 3 )
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The following three tasks are used to demonstrate the peeking behaviour.
+ * Each task is given a different priority to demonstrate the order in which
+ * tasks are woken as data is peeked from a queue.
+ */
+static void prvLowPriorityPeekTask(void *pvParameters);
+static void prvMediumPriorityPeekTask(void *pvParameters);
+static void prvHighPriorityPeekTask(void *pvParameters);
+static void prvHighestPriorityPeekTask(void *pvParameters);
+
+/*-----------------------------------------------------------*/
+
+/* Flag that will be latched to pdTRUE should any unexpected behaviour be
+detected in any of the tasks. */
+static volatile portBASE_TYPE xErrorDetected = pdFALSE;
+
+/* Counter that is incremented on each cycle of a test.  This is used to
+detect a stalled task - a test that is no longer running. */
+static volatile unsigned portLONG ulLoopCounter = 0;
+
+/* Handles to the test tasks. */
+xTaskHandle xMediumPriorityTask, xHighPriorityTask, xHighestPriorityTask;
+/*-----------------------------------------------------------*/
+
+void vStartQueuePeekTasks(void)
+{
+	xQueueHandle xQueue;
+
+	/* Create the queue that we are going to use for the test/demo. */
+	xQueue = xQueueCreate(qpeekQUEUE_LENGTH, sizeof(unsigned portLONG));
+
+	/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
+	in use.  The queue registry is provided as a means for kernel aware
+	debuggers to locate queues and has no purpose if a kernel aware debugger
+	is not being used.  The call to vQueueAddToRegistry() will be removed
+	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+	defined to be less than 1. */
+	vQueueAddToRegistry(xQueue, (signed portCHAR *) "QPeek_Test_Queue");
+
+	/* Create the demo tasks and pass it the queue just created.  We are
+	passing the queue handle by value so it does not matter that it is declared
+	on the stack here. */
+	xTaskCreate(prvLowPriorityPeekTask, (signed portCHAR *)"PeekL", configMINIMAL_STACK_SIZE, (void *) xQueue, qpeekLOW_PRIORITY, NULL);
+	xTaskCreate(prvMediumPriorityPeekTask, (signed portCHAR *)"PeekM", configMINIMAL_STACK_SIZE, (void *) xQueue, qpeekMEDIUM_PRIORITY, &xMediumPriorityTask);
+	xTaskCreate(prvHighPriorityPeekTask, (signed portCHAR *)"PeekH1", configMINIMAL_STACK_SIZE, (void *) xQueue, qpeekHIGH_PRIORITY, &xHighPriorityTask);
+	xTaskCreate(prvHighestPriorityPeekTask, (signed portCHAR *)"PeekH2", configMINIMAL_STACK_SIZE, (void *) xQueue, qpeekHIGHEST_PRIORITY, &xHighestPriorityTask);
+}
+/*-----------------------------------------------------------*/
+
+static void prvHighestPriorityPeekTask(void *pvParameters)
+{
+	xQueueHandle xQueue = (xQueueHandle) pvParameters;
+	unsigned portLONG ulValue;
+
+#ifdef USE_STDIO
+	{
+		void vPrintDisplayMessage(const portCHAR * const * ppcMessageToSend);
+
+		const portCHAR * const pcTaskStartMsg = "Queue peek test started.\r\n";
+
+		/* Queue a message for printing to say the task has started. */
+		vPrintDisplayMessage(&pcTaskStartMsg);
+	}
+#endif
+
+	for (;;) {
+		/* Try peeking from the queue.  The queue should be empty so we will
+		block, allowing the high priority task to execute. */
+		if (xQueuePeek(xQueue, &ulValue, portMAX_DELAY) != pdPASS) {
+			/* We expected to have received something by the time we unblock. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* When we reach here the high and medium priority tasks should still
+		be blocked on the queue.  We unblocked because the low priority task
+		wrote a value to the queue, which we should have peeked.  Peeking the
+		data (rather than receiving it) will leave the data on the queue, so
+		the high priority task should then have also been unblocked, but not
+		yet executed. */
+		if (ulValue != 0x11223344) {
+			/* We did not receive the expected value. */
+			xErrorDetected = pdTRUE;
+		}
+
+		if (uxQueueMessagesWaiting(xQueue) != 1) {
+			/* The message should have been left on the queue. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Now we are going to actually receive the data, so when the high
+		priority task runs it will find the queue empty and return to the
+		blocked state. */
+		ulValue = 0;
+		if (xQueueReceive(xQueue, &ulValue, qpeekNO_BLOCK) != pdPASS) {
+			/* We expected to receive the value. */
+			xErrorDetected = pdTRUE;
+		}
+
+		if (ulValue != 0x11223344) {
+			/* We did not receive the expected value - which should have been
+			the same value as was peeked. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Now we will block again as the queue is once more empty.  The low
+		priority task can then execute again. */
+		if (xQueuePeek(xQueue, &ulValue, portMAX_DELAY) != pdPASS) {
+			/* We expected to have received something by the time we unblock. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* When we get here the low priority task should have again written to the
+		queue. */
+		if (ulValue != 0x01234567) {
+			/* We did not receive the expected value. */
+			xErrorDetected = pdTRUE;
+		}
+
+		if (uxQueueMessagesWaiting(xQueue) != 1) {
+			/* The message should have been left on the queue. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* We only peeked the data, so suspending ourselves now should enable
+		the high priority task to also peek the data.  The high priority task
+		will have been unblocked when we peeked the data as we left the data
+		in the queue. */
+		vTaskSuspend(NULL);
+
+
+
+		/* This time we are going to do the same as the above test, but the
+		high priority task is going to receive the data, rather than peek it.
+		This means that the medium priority task should never peek the value. */
+		if (xQueuePeek(xQueue, &ulValue, portMAX_DELAY) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (ulValue != 0xaabbaabb) {
+			xErrorDetected = pdTRUE;
+		}
+
+		vTaskSuspend(NULL);
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvHighPriorityPeekTask(void *pvParameters)
+{
+	xQueueHandle xQueue = (xQueueHandle) pvParameters;
+	unsigned portLONG ulValue;
+
+	for (;;) {
+		/* Try peeking from the queue.  The queue should be empty so we will
+		block, allowing the medium priority task to execute.  Both the high
+		and highest priority tasks will then be blocked on the queue. */
+		if (xQueuePeek(xQueue, &ulValue, portMAX_DELAY) != pdPASS) {
+			/* We expected to have received something by the time we unblock. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* When we get here the highest priority task should have peeked the data
+		(unblocking this task) then suspended (allowing this task to also peek
+		the data). */
+		if (ulValue != 0x01234567) {
+			/* We did not receive the expected value. */
+			xErrorDetected = pdTRUE;
+		}
+
+		if (uxQueueMessagesWaiting(xQueue) != 1) {
+			/* The message should have been left on the queue. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* We only peeked the data, so suspending ourselves now should enable
+		the medium priority task to also peek the data.  The medium priority task
+		will have been unblocked when we peeked the data as we left the data
+		in the queue. */
+		vTaskSuspend(NULL);
+
+
+		/* This time we are going actually receive the value, so the medium
+		priority task will never peek the data - we removed it from the queue. */
+		if (xQueueReceive(xQueue, &ulValue, portMAX_DELAY) != pdPASS) {
+			xErrorDetected = pdTRUE;
+		}
+
+		if (ulValue != 0xaabbaabb) {
+			xErrorDetected = pdTRUE;
+		}
+
+		vTaskSuspend(NULL);
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvMediumPriorityPeekTask(void *pvParameters)
+{
+	xQueueHandle xQueue = (xQueueHandle) pvParameters;
+	unsigned portLONG ulValue;
+
+	for (;;) {
+		/* Try peeking from the queue.  The queue should be empty so we will
+		block, allowing the low priority task to execute.  The highest, high
+		and medium priority tasks will then all be blocked on the queue. */
+		if (xQueuePeek(xQueue, &ulValue, portMAX_DELAY) != pdPASS) {
+			/* We expected to have received something by the time we unblock. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* When we get here the high priority task should have peeked the data
+		(unblocking this task) then suspended (allowing this task to also peek
+		the data). */
+		if (ulValue != 0x01234567) {
+			/* We did not receive the expected value. */
+			xErrorDetected = pdTRUE;
+		}
+
+		if (uxQueueMessagesWaiting(xQueue) != 1) {
+			/* The message should have been left on the queue. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Just so we know the test is still running. */
+		ulLoopCounter++;
+
+		/* Now we can suspend ourselves so the low priority task can execute
+		again. */
+		vTaskSuspend(NULL);
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvLowPriorityPeekTask(void *pvParameters)
+{
+	xQueueHandle xQueue = (xQueueHandle) pvParameters;
+	unsigned portLONG ulValue;
+
+	for (;;) {
+		/* Write some data to the queue.  This should unblock the highest
+		priority task that is waiting to peek data from the queue. */
+		ulValue = 0x11223344;
+		if (xQueueSendToBack(xQueue, &ulValue, qpeekNO_BLOCK) != pdPASS) {
+			/* We were expecting the queue to be empty so we should not of
+			had a problem writing to the queue. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* By the time we get here the data should have been removed from
+		the queue. */
+		if (uxQueueMessagesWaiting(xQueue) != 0) {
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Write another value to the queue, again waking the highest priority
+		task that is blocked on the queue. */
+		ulValue = 0x01234567;
+		if (xQueueSendToBack(xQueue, &ulValue, qpeekNO_BLOCK) != pdPASS) {
+			/* We were expecting the queue to be empty so we should not of
+			had a problem writing to the queue. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* All the other tasks should now have successfully peeked the data.
+		The data is still in the queue so we should be able to receive it. */
+		ulValue = 0;
+		if (xQueueReceive(xQueue, &ulValue, qpeekNO_BLOCK) != pdPASS) {
+			/* We expected to receive the data. */
+			xErrorDetected = pdTRUE;
+		}
+
+		if (ulValue != 0x01234567) {
+			/* We did not receive the expected value. */
+		}
+
+		/* Lets just delay a while as this is an intensive test as we don't
+		want to starve other tests of processing time. */
+		vTaskDelay(qpeekSHORT_DELAY);
+
+		/* Unsuspend the other tasks so we can repeat the test - this time
+		however not all the other tasks will peek the data as the high
+		priority task is actually going to remove it from the queue.  Send
+		to front is used just to be different.  As the queue is empty it
+		makes no difference to the result. */
+		vTaskResume(xMediumPriorityTask);
+		vTaskResume(xHighPriorityTask);
+		vTaskResume(xHighestPriorityTask);
+
+		ulValue = 0xaabbaabb;
+		if (xQueueSendToFront(xQueue, &ulValue, qpeekNO_BLOCK) != pdPASS) {
+			/* We were expecting the queue to be empty so we should not of
+			had a problem writing to the queue. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* This time we should find that the queue is empty.  The high priority
+		task actually removed the data rather than just peeking it. */
+		if (xQueuePeek(xQueue, &ulValue, qpeekNO_BLOCK) != errQUEUE_EMPTY) {
+			/* We expected to receive the data. */
+			xErrorDetected = pdTRUE;
+		}
+
+		/* Unsuspend the highest and high priority tasks so we can go back
+		and repeat the whole thing.  The medium priority task should not be
+		suspended as it was not able to peek the data in this last case. */
+		vTaskResume(xHighPriorityTask);
+		vTaskResume(xHighestPriorityTask);
+
+		/* Lets just delay a while as this is an intensive test as we don't
+		want to starve other tests of processing time. */
+		vTaskDelay(qpeekSHORT_DELAY);
+	}
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreQueuePeekTasksStillRunning(void)
+{
+	static unsigned portLONG ulLastLoopCounter = 0;
+
+	/* If the demo task is still running then we expect the loopcounter to
+	have incremented since this function was last called. */
+	if (ulLastLoopCounter == ulLoopCounter) {
+		xErrorDetected = pdTRUE;
+	}
+
+	ulLastLoopCounter = ulLoopCounter;
+
+	/* Errors detected in the task itself will have latched xErrorDetected
+	to true. */
+
+	return !xErrorDetected;
+}
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/blocktim.c b/gyro_board/src/usb/CommonDemoTasks/blocktim.c
new file mode 100644
index 0000000..0174cee
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/blocktim.c
@@ -0,0 +1,456 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*
+ * This file contains some test scenarios that ensure tasks do not exit queue
+ * send or receive functions prematurely.  A description of the tests is
+ * included within the code.
+ */
+
+/* Kernel includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+/* Demo includes. */
+#include "blocktim.h"
+
+/* Task priorities.  Allow these to be overridden. */
+#ifndef bktPRIMARY_PRIORITY
+#define bktPRIMARY_PRIORITY			( 3 )
+#endif
+
+#ifndef bktSECONDARY_PRIORITY
+#define bktSECONDARY_PRIORITY		( 2 )
+#endif
+
+/* Task behaviour. */
+#define bktQUEUE_LENGTH				( 5 )
+#define bktSHORT_WAIT				( ( ( portTickType ) 20 ) / portTICK_RATE_MS )
+#define bktPRIMARY_BLOCK_TIME		( 10 )
+#define bktALLOWABLE_MARGIN			( 15 )
+#define bktTIME_TO_BLOCK			( 175 )
+#define bktDONT_BLOCK				( ( portTickType ) 0 )
+#define bktRUN_INDICATOR			( ( unsigned portBASE_TYPE ) 0x55 )
+
+/* The queue on which the tasks block. */
+static xQueueHandle xTestQueue;
+
+/* Handle to the secondary task is required by the primary task for calls
+to vTaskSuspend/Resume(). */
+static xTaskHandle xSecondary;
+
+/* Used to ensure that tasks are still executing without error. */
+static volatile portBASE_TYPE xPrimaryCycles = 0, xSecondaryCycles = 0;
+static volatile portBASE_TYPE xErrorOccurred = pdFALSE;
+
+/* Provides a simple mechanism for the primary task to know when the
+secondary task has executed. */
+static volatile unsigned portBASE_TYPE xRunIndicator;
+
+/* The two test tasks.  Their behaviour is commented within the files. */
+static void vPrimaryBlockTimeTestTask(void *pvParameters);
+static void vSecondaryBlockTimeTestTask(void *pvParameters);
+
+/*-----------------------------------------------------------*/
+
+void vCreateBlockTimeTasks(void)
+{
+	/* Create the queue on which the two tasks block. */
+	xTestQueue = xQueueCreate(bktQUEUE_LENGTH, sizeof(portBASE_TYPE));
+
+	/* vQueueAddToRegistry() adds the queue to the queue registry, if one is
+	in use.  The queue registry is provided as a means for kernel aware
+	debuggers to locate queues and has no purpose if a kernel aware debugger
+	is not being used.  The call to vQueueAddToRegistry() will be removed
+	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+	defined to be less than 1. */
+	vQueueAddToRegistry(xTestQueue, (signed char *) "Block_Time_Queue");
+
+	/* Create the two test tasks. */
+	xTaskCreate(vPrimaryBlockTimeTestTask, (signed char *)"BTest1", configMINIMAL_STACK_SIZE, NULL, bktPRIMARY_PRIORITY, NULL);
+	xTaskCreate(vSecondaryBlockTimeTestTask, (signed char *)"BTest2", configMINIMAL_STACK_SIZE, NULL, bktSECONDARY_PRIORITY, &xSecondary);
+}
+/*-----------------------------------------------------------*/
+
+static void vPrimaryBlockTimeTestTask(void *pvParameters)
+{
+	portBASE_TYPE xItem, xData;
+	portTickType xTimeWhenBlocking;
+	portTickType xTimeToBlock, xBlockedTime;
+
+	(void) pvParameters;
+
+	for (;;) {
+		/*********************************************************************
+		Test 1
+
+		Simple block time wakeup test on queue receives. */
+		for (xItem = 0; xItem < bktQUEUE_LENGTH; xItem++) {
+			/* The queue is empty. Attempt to read from the queue using a block
+			time.  When we wake, ensure the delta in time is as expected. */
+			xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
+
+			xTimeWhenBlocking = xTaskGetTickCount();
+
+			/* We should unblock after xTimeToBlock having not received
+			anything on the queue. */
+			if (xQueueReceive(xTestQueue, &xData, xTimeToBlock) != errQUEUE_EMPTY) {
+				xErrorOccurred = pdTRUE;
+			}
+
+			/* How long were we blocked for? */
+			xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+			if (xBlockedTime < xTimeToBlock) {
+				/* Should not have blocked for less than we requested. */
+				xErrorOccurred = pdTRUE;
+			}
+
+			if (xBlockedTime > (xTimeToBlock + bktALLOWABLE_MARGIN)) {
+				/* Should not have blocked for longer than we requested,
+				although we would not necessarily run as soon as we were
+				unblocked so a margin is allowed. */
+				xErrorOccurred = pdTRUE;
+			}
+		}
+
+		/*********************************************************************
+		Test 2
+
+		Simple block time wakeup test on queue sends.
+
+		First fill the queue.  It should be empty so all sends should pass. */
+		for (xItem = 0; xItem < bktQUEUE_LENGTH; xItem++) {
+			if (xQueueSend(xTestQueue, &xItem, bktDONT_BLOCK) != pdPASS) {
+				xErrorOccurred = pdTRUE;
+			}
+
+#if configUSE_PREEMPTION == 0
+			taskYIELD();
+#endif
+		}
+
+		for (xItem = 0; xItem < bktQUEUE_LENGTH; xItem++) {
+			/* The queue is full. Attempt to write to the queue using a block
+			time.  When we wake, ensure the delta in time is as expected. */
+			xTimeToBlock = bktPRIMARY_BLOCK_TIME << xItem;
+
+			xTimeWhenBlocking = xTaskGetTickCount();
+
+			/* We should unblock after xTimeToBlock having not received
+			anything on the queue. */
+			if (xQueueSend(xTestQueue, &xItem, xTimeToBlock) != errQUEUE_FULL) {
+				xErrorOccurred = pdTRUE;
+			}
+
+			/* How long were we blocked for? */
+			xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+			if (xBlockedTime < xTimeToBlock) {
+				/* Should not have blocked for less than we requested. */
+				xErrorOccurred = pdTRUE;
+			}
+
+			if (xBlockedTime > (xTimeToBlock + bktALLOWABLE_MARGIN)) {
+				/* Should not have blocked for longer than we requested,
+				although we would not necessarily run as soon as we were
+				unblocked so a margin is allowed. */
+				xErrorOccurred = pdTRUE;
+			}
+		}
+
+		/*********************************************************************
+		Test 3
+
+		Wake the other task, it will block attempting to post to the queue.
+		When we read from the queue the other task will wake, but before it
+		can run we will post to the queue again.  When the other task runs it
+		will find the queue still full, even though it was woken.  It should
+		recognise that its block time has not expired and return to block for
+		the remains of its block time.
+
+		Wake the other task so it blocks attempting to post to the already
+		full queue. */
+		xRunIndicator = 0;
+		vTaskResume(xSecondary);
+
+		/* We need to wait a little to ensure the other task executes. */
+		while (xRunIndicator != bktRUN_INDICATOR) {
+			/* The other task has not yet executed. */
+			vTaskDelay(bktSHORT_WAIT);
+		}
+		/* Make sure the other task is blocked on the queue. */
+		vTaskDelay(bktSHORT_WAIT);
+		xRunIndicator = 0;
+
+		for (xItem = 0; xItem < bktQUEUE_LENGTH; xItem++) {
+			/* Now when we make space on the queue the other task should wake
+			but not execute as this task has higher priority. */
+			if (xQueueReceive(xTestQueue, &xData, bktDONT_BLOCK) != pdPASS) {
+				xErrorOccurred = pdTRUE;
+			}
+
+			/* Now fill the queue again before the other task gets a chance to
+			execute.  If the other task had executed we would find the queue
+			full ourselves, and the other task have set xRunIndicator. */
+			if (xQueueSend(xTestQueue, &xItem, bktDONT_BLOCK) != pdPASS) {
+				xErrorOccurred = pdTRUE;
+			}
+
+			if (xRunIndicator == bktRUN_INDICATOR) {
+				/* The other task should not have executed. */
+				xErrorOccurred = pdTRUE;
+			}
+
+			/* Raise the priority of the other task so it executes and blocks
+			on the queue again. */
+			vTaskPrioritySet(xSecondary, bktPRIMARY_PRIORITY + 2);
+
+			/* The other task should now have re-blocked without exiting the
+			queue function. */
+			if (xRunIndicator == bktRUN_INDICATOR) {
+				/* The other task should not have executed outside of the
+				queue function. */
+				xErrorOccurred = pdTRUE;
+			}
+
+			/* Set the priority back down. */
+			vTaskPrioritySet(xSecondary, bktSECONDARY_PRIORITY);
+		}
+
+		/* Let the other task timeout.  When it unblockes it will check that it
+		unblocked at the correct time, then suspend itself. */
+		while (xRunIndicator != bktRUN_INDICATOR) {
+			vTaskDelay(bktSHORT_WAIT);
+		}
+		vTaskDelay(bktSHORT_WAIT);
+		xRunIndicator = 0;
+
+
+		/*********************************************************************
+		Test 4
+
+		As per test 3 - but with the send and receive the other way around.
+		The other task blocks attempting to read from the queue.
+
+		Empty the queue.  We should find that it is full. */
+		for (xItem = 0; xItem < bktQUEUE_LENGTH; xItem++) {
+			if (xQueueReceive(xTestQueue, &xData, bktDONT_BLOCK) != pdPASS) {
+				xErrorOccurred = pdTRUE;
+			}
+		}
+
+		/* Wake the other task so it blocks attempting to read from  the
+		already	empty queue. */
+		vTaskResume(xSecondary);
+
+		/* We need to wait a little to ensure the other task executes. */
+		while (xRunIndicator != bktRUN_INDICATOR) {
+			vTaskDelay(bktSHORT_WAIT);
+		}
+		vTaskDelay(bktSHORT_WAIT);
+		xRunIndicator = 0;
+
+		for (xItem = 0; xItem < bktQUEUE_LENGTH; xItem++) {
+			/* Now when we place an item on the queue the other task should
+			wake but not execute as this task has higher priority. */
+			if (xQueueSend(xTestQueue, &xItem, bktDONT_BLOCK) != pdPASS) {
+				xErrorOccurred = pdTRUE;
+			}
+
+			/* Now empty the queue again before the other task gets a chance to
+			execute.  If the other task had executed we would find the queue
+			empty ourselves, and the other task would be suspended. */
+			if (xQueueReceive(xTestQueue, &xData, bktDONT_BLOCK) != pdPASS) {
+				xErrorOccurred = pdTRUE;
+			}
+
+			if (xRunIndicator == bktRUN_INDICATOR) {
+				/* The other task should not have executed. */
+				xErrorOccurred = pdTRUE;
+			}
+
+			/* Raise the priority of the other task so it executes and blocks
+			on the queue again. */
+			vTaskPrioritySet(xSecondary, bktPRIMARY_PRIORITY + 2);
+
+			/* The other task should now have re-blocked without exiting the
+			queue function. */
+			if (xRunIndicator == bktRUN_INDICATOR) {
+				/* The other task should not have executed outside of the
+				queue function. */
+				xErrorOccurred = pdTRUE;
+			}
+			vTaskPrioritySet(xSecondary, bktSECONDARY_PRIORITY);
+		}
+
+		/* Let the other task timeout.  When it unblockes it will check that it
+		unblocked at the correct time, then suspend itself. */
+		while (xRunIndicator != bktRUN_INDICATOR) {
+			vTaskDelay(bktSHORT_WAIT);
+		}
+		vTaskDelay(bktSHORT_WAIT);
+
+		xPrimaryCycles++;
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void vSecondaryBlockTimeTestTask(void *pvParameters)
+{
+	portTickType xTimeWhenBlocking, xBlockedTime;
+	portBASE_TYPE xData;
+
+	(void) pvParameters;
+
+	for (;;) {
+		/*********************************************************************
+		Test 1 and 2
+
+		This task does does not participate in these tests. */
+		vTaskSuspend(NULL);
+
+		/*********************************************************************
+		Test 3
+
+		The first thing we do is attempt to read from the queue.  It should be
+		full so we block.  Note the time before we block so we can check the
+		wake time is as per that expected. */
+		xTimeWhenBlocking = xTaskGetTickCount();
+
+		/* We should unblock after bktTIME_TO_BLOCK having not sent
+		anything to the queue. */
+		xData = 0;
+		xRunIndicator = bktRUN_INDICATOR;
+		if (xQueueSend(xTestQueue, &xData, bktTIME_TO_BLOCK) != errQUEUE_FULL) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		/* How long were we inside the send function? */
+		xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+		/* We should not have blocked for less time than bktTIME_TO_BLOCK. */
+		if (xBlockedTime < bktTIME_TO_BLOCK) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		/* We should of not blocked for much longer than bktALLOWABLE_MARGIN
+		either.  A margin is permitted as we would not necessarily run as
+		soon as we unblocked. */
+		if (xBlockedTime > (bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN)) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		/* Suspend ready for test 3. */
+		xRunIndicator = bktRUN_INDICATOR;
+		vTaskSuspend(NULL);
+
+		/*********************************************************************
+		Test 4
+
+		As per test three, but with the send and receive reversed. */
+		xTimeWhenBlocking = xTaskGetTickCount();
+
+		/* We should unblock after bktTIME_TO_BLOCK having not received
+		anything on the queue. */
+		xRunIndicator = bktRUN_INDICATOR;
+		if (xQueueReceive(xTestQueue, &xData, bktTIME_TO_BLOCK) != errQUEUE_EMPTY) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		xBlockedTime = xTaskGetTickCount() - xTimeWhenBlocking;
+
+		/* We should not have blocked for less time than bktTIME_TO_BLOCK. */
+		if (xBlockedTime < bktTIME_TO_BLOCK) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		/* We should of not blocked for much longer than bktALLOWABLE_MARGIN
+		either.  A margin is permitted as we would not necessarily run as soon
+		as we unblocked. */
+		if (xBlockedTime > (bktTIME_TO_BLOCK + bktALLOWABLE_MARGIN)) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		xRunIndicator = bktRUN_INDICATOR;
+
+		xSecondaryCycles++;
+	}
+}
+/*-----------------------------------------------------------*/
+
+portBASE_TYPE xAreBlockTimeTestTasksStillRunning(void)
+{
+	static portBASE_TYPE xLastPrimaryCycleCount = 0, xLastSecondaryCycleCount = 0;
+	portBASE_TYPE xReturn = pdPASS;
+
+	/* Have both tasks performed at least one cycle since this function was
+	last called? */
+	if (xPrimaryCycles == xLastPrimaryCycleCount) {
+		xReturn = pdFAIL;
+	}
+
+	if (xSecondaryCycles == xLastSecondaryCycleCount) {
+		xReturn = pdFAIL;
+	}
+
+	if (xErrorOccurred == pdTRUE) {
+		xReturn = pdFAIL;
+	}
+
+	xLastSecondaryCycleCount = xSecondaryCycles;
+	xLastPrimaryCycleCount = xPrimaryCycles;
+
+	return xReturn;
+}
diff --git a/gyro_board/src/usb/CommonDemoTasks/flash.c b/gyro_board/src/usb/CommonDemoTasks/flash.c
new file mode 100644
index 0000000..fadc899
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/flash.c
@@ -0,0 +1,146 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/**
+ * This version of flash .c is for use on systems that have limited stack space
+ * and no display facilities.  The complete version can be found in the
+ * Demo/Common/Full directory.
+ *
+ * Three tasks are created, each of which flash an LED at a different rate.  The first
+ * LED flashes every 200ms, the second every 400ms, the third every 600ms.
+ *
+ * The LED flash tasks provide instant visual feedback.  They show that the scheduler
+ * is still operational.
+ *
+ */
+
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Demo program include files. */
+#include "partest.h"
+#include "flash.h"
+
+#define ledSTACK_SIZE		configMINIMAL_STACK_SIZE
+#define ledNUMBER_OF_LEDS	( 3 )
+#define ledFLASH_RATE_BASE	( ( portTickType ) 333 )
+
+/* Variable used by the created tasks to calculate the LED number to use, and
+the rate at which they should flash the LED. */
+static volatile unsigned portBASE_TYPE uxFlashTaskNumber = 0;
+
+/* The task that is created three times. */
+static portTASK_FUNCTION_PROTO(vLEDFlashTask, pvParameters);
+
+/*-----------------------------------------------------------*/
+
+// To continually print out the serial output, run the following command.
+// while true; do [ `ls /dev/ttyACM* 2>/dev/null` ] && ls /dev/ttyACM* | python -c "import sys; x = sys.stdin.readline()[:-1].split(' ')[0]; sys.stderr.write('Connecting to %s\n' % (x,)); print x" | xargs cat || sleep 0.25;  done
+
+void vStartLEDFlashTasks(unsigned portBASE_TYPE uxPriority)
+{
+	signed portBASE_TYPE xLEDTask;
+
+	/* Create the three tasks. */
+	for (xLEDTask = 0; xLEDTask < ledNUMBER_OF_LEDS; ++xLEDTask) {
+		/* Spawn the task. */
+		xTaskCreate(vLEDFlashTask, (signed char *) "LEDx", ledSTACK_SIZE, NULL, uxPriority, (xTaskHandle *) NULL);
+	}
+}
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION(vLEDFlashTask, pvParameters)
+{
+	portTickType xFlashRate, xLastFlashTime;
+	unsigned portBASE_TYPE uxLED;
+
+	/* The parameters are not used. */
+	(void) pvParameters;
+
+	/* Calculate the LED and flash rate. */
+	portENTER_CRITICAL();
+	{
+		/* See which of the eight LED's we should use. */
+		uxLED = uxFlashTaskNumber;
+
+		/* Update so the next task uses the next LED. */
+		uxFlashTaskNumber++;
+	}
+	portEXIT_CRITICAL();
+
+	xFlashRate = ledFLASH_RATE_BASE + (ledFLASH_RATE_BASE * (portTickType) uxLED);
+	xFlashRate /= portTICK_RATE_MS;
+
+	/* We will turn the LED on and off again in the delay period, so each
+	delay is only half the total period. */
+	xFlashRate /= (portTickType) 2;
+
+	/* We need to initialise xLastFlashTime prior to the first call to
+	vTaskDelayUntil(). */
+	xLastFlashTime = xTaskGetTickCount();
+
+	for (;;) {
+		/* Delay for half the flash period then turn the LED on. */
+		vTaskDelayUntil(&xLastFlashTime, xFlashRate);
+		vParTestToggleLED(uxLED);
+
+		/* Delay for half the flash period then turn the LED off. */
+		vTaskDelayUntil(&xLastFlashTime, xFlashRate);
+		vParTestToggleLED(uxLED);
+	}
+} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/AltBlckQ.h b/gyro_board/src/usb/CommonDemoTasks/include/AltBlckQ.h
new file mode 100644
index 0000000..dad37ba
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/AltBlckQ.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef ALT_BLOCK_Q_H
+#define ALT_BLOCK_Q_H
+
+void vStartAltBlockingQueueTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xAreAltBlockingQueuesStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/AltBlock.h b/gyro_board/src/usb/CommonDemoTasks/include/AltBlock.h
new file mode 100644
index 0000000..caa0516
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/AltBlock.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef FAST_BLOCK_TIME_TEST_H
+#define FAST_BLOCK_TIME_TEST_H
+
+void vCreateAltBlockTimeTasks(void);
+portBASE_TYPE xAreAltBlockTimeTestTasksStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/AltPollQ.h b/gyro_board/src/usb/CommonDemoTasks/include/AltPollQ.h
new file mode 100644
index 0000000..66ac04e
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/AltPollQ.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef ALT_POLLED_Q_H
+#define ALT_POLLED_Q_H
+
+void vStartAltPolledQueueTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xAreAltPollingQueuesStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/AltQTest.h b/gyro_board/src/usb/CommonDemoTasks/include/AltQTest.h
new file mode 100644
index 0000000..b8cc24d
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/AltQTest.h
@@ -0,0 +1,63 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef FAST_GEN_Q_TEST_H
+#define FAST_GEN_Q_TEST_H
+
+void vStartAltGenericQueueTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xAreAltGenericQueueTasksStillRunning(void);
+
+#endif /* GEN_Q_TEST_H */
+
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/BlockQ.h b/gyro_board/src/usb/CommonDemoTasks/include/BlockQ.h
new file mode 100644
index 0000000..30ea0e1
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/BlockQ.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef BLOCK_Q_H
+#define BLOCK_Q_H
+
+void vStartBlockingQueueTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xAreBlockingQueuesStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/GenQTest.h b/gyro_board/src/usb/CommonDemoTasks/include/GenQTest.h
new file mode 100644
index 0000000..32a2718
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/GenQTest.h
@@ -0,0 +1,63 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef GEN_Q_TEST_H
+#define GEN_Q_TEST_H
+
+void vStartGenericQueueTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xAreGenericQueueTasksStillRunning(void);
+
+#endif /* GEN_Q_TEST_H */
+
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/IntQueue.h b/gyro_board/src/usb/CommonDemoTasks/include/IntQueue.h
new file mode 100644
index 0000000..514e458
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/IntQueue.h
@@ -0,0 +1,68 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef QUEUE_ACCESS_TEST
+#define QUEUE_ACCESS_TEST
+
+void vStartInterruptQueueTasks(void);
+portBASE_TYPE xAreIntQueueTasksStillRunning(void);
+portBASE_TYPE xFirstTimerHandler(void);
+portBASE_TYPE xSecondTimerHandler(void);
+
+#endif /* QUEUE_ACCESS_TEST */
+
+
+
+
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/PollQ.h b/gyro_board/src/usb/CommonDemoTasks/include/PollQ.h
new file mode 100644
index 0000000..096b820
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/PollQ.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef POLLED_Q_H
+#define POLLED_Q_H
+
+void vStartPolledQueueTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xArePollingQueuesStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/QPeek.h b/gyro_board/src/usb/CommonDemoTasks/include/QPeek.h
new file mode 100644
index 0000000..2666ebd
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/QPeek.h
@@ -0,0 +1,63 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef Q_PEEK_TEST_H
+#define Q_PEEK_TEST_H
+
+void vStartQueuePeekTasks(void);
+portBASE_TYPE xAreQueuePeekTasksStillRunning(void);
+
+#endif /* Q_PEEK_TEST_H */
+
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/blocktim.h b/gyro_board/src/usb/CommonDemoTasks/include/blocktim.h
new file mode 100644
index 0000000..72fac90
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/blocktim.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef BLOCK_TIME_TEST_H
+#define BLOCK_TIME_TEST_H
+
+void vCreateBlockTimeTasks(void);
+portBASE_TYPE xAreBlockTimeTestTasksStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/comtest.h b/gyro_board/src/usb/CommonDemoTasks/include/comtest.h
new file mode 100644
index 0000000..df974e2
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/comtest.h
@@ -0,0 +1,63 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef COMTEST_H
+#define COMTEST_H
+
+void vAltStartComTestTasks(unsigned portBASE_TYPE uxPriority, unsigned long ulBaudRate, unsigned portBASE_TYPE uxLED);
+void vStartComTestTasks(unsigned portBASE_TYPE uxPriority, eCOMPort ePort, eBaud eBaudRate);
+portBASE_TYPE xAreComTestTasksStillRunning(void);
+void vComTestUnsuspendTask(void);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/comtest2.h b/gyro_board/src/usb/CommonDemoTasks/include/comtest2.h
new file mode 100644
index 0000000..18beab0
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/comtest2.h
@@ -0,0 +1,61 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef COMTEST_H
+#define COMTEST_H
+
+void vAltStartComTestTasks(unsigned portBASE_TYPE uxPriority, unsigned long ulBaudRate, unsigned portBASE_TYPE uxLED);
+portBASE_TYPE xAreComTestTasksStillRunning(void);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/countsem.h b/gyro_board/src/usb/CommonDemoTasks/include/countsem.h
new file mode 100644
index 0000000..d08db7b
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/countsem.h
@@ -0,0 +1,61 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef COUNT_SEMAPHORE_TEST_H
+#define COUNT_SEMAPHORE_TEST_H
+
+void vStartCountingSemaphoreTasks(void);
+portBASE_TYPE xAreCountingSemaphoreTasksStillRunning(void);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/crflash.h b/gyro_board/src/usb/CommonDemoTasks/include/crflash.h
new file mode 100644
index 0000000..6a5f715
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/crflash.h
@@ -0,0 +1,73 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef CRFLASH_LED_H
+#define CRFLASH_LED_H
+
+/*
+ * Create the co-routines used to flash the LED's at different rates.
+ *
+ * @param uxPriority The number of 'fixed delay' co-routines to create.  This
+ *		  also effects the number of LED's that will be utilised.  For example,
+ *		  passing in 3 will cause LED's 0 to 2 to be utilised.
+ */
+void vStartFlashCoRoutines(unsigned portBASE_TYPE uxPriority);
+
+/*
+ * Return pdPASS or pdFAIL depending on whether an error has been detected
+ * or not.
+ */
+portBASE_TYPE xAreFlashCoRoutinesStillRunning(void);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/crhook.h b/gyro_board/src/usb/CommonDemoTasks/include/crhook.h
new file mode 100644
index 0000000..370677f
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/crhook.h
@@ -0,0 +1,69 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef CRHOOK_H
+#define CRHOOK_H
+
+/*
+ * Create the co-routines used to communicate wit the tick hook.
+ */
+void vStartHookCoRoutines(void);
+
+/*
+ * Return pdPASS or pdFAIL depending on whether an error has been detected
+ * or not.
+ */
+portBASE_TYPE xAreHookCoRoutinesStillRunning(void);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/death.h b/gyro_board/src/usb/CommonDemoTasks/include/death.h
new file mode 100644
index 0000000..155f4f1
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/death.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef SUICIDE_TASK_H
+#define SUICIDE_TASK_H
+
+void vCreateSuicidalTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xIsCreateTaskStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/dynamic.h b/gyro_board/src/usb/CommonDemoTasks/include/dynamic.h
new file mode 100644
index 0000000..b2bf281
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/dynamic.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef DYNAMIC_MANIPULATION_H
+#define DYNAMIC_MANIPULATION_H
+
+void vStartDynamicPriorityTasks(void);
+portBASE_TYPE xAreDynamicPriorityTasksStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/fileIO.h b/gyro_board/src/usb/CommonDemoTasks/include/fileIO.h
new file mode 100644
index 0000000..9f3c7e0
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/fileIO.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef FILE_IO_H
+#define FILE_OI_H
+
+void vDisplayMessage(const char * const pcMessageToPrint);
+void vWriteMessageToDisk(const char * const pcMessage);
+void vWriteBufferToDisk(const char * const pcBuffer, unsigned long ulBufferLength);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/flash.h b/gyro_board/src/usb/CommonDemoTasks/include/flash.h
new file mode 100644
index 0000000..008df24
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/flash.h
@@ -0,0 +1,60 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef FLASH_LED_H
+#define FLASH_LED_H
+
+void vStartLEDFlashTasks(unsigned portBASE_TYPE uxPriority);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/flop.h b/gyro_board/src/usb/CommonDemoTasks/include/flop.h
new file mode 100644
index 0000000..2e5fb79
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/flop.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef FLOP_TASKS_H
+#define FLOP_TASKS_H
+
+void vStartMathTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xAreMathsTaskStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/integer.h b/gyro_board/src/usb/CommonDemoTasks/include/integer.h
new file mode 100644
index 0000000..0bdf620
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/integer.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef INTEGER_TASKS_H
+#define INTEGER_TASKS_H
+
+void vStartIntegerMathTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xAreIntegerMathsTaskStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/mevents.h b/gyro_board/src/usb/CommonDemoTasks/include/mevents.h
new file mode 100644
index 0000000..5452d4b
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/mevents.h
@@ -0,0 +1,62 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef EVENTS_TEST_H
+#define EVENTS_TEST_H
+
+void vStartMultiEventTasks(void);
+portBASE_TYPE xAreMultiEventTasksStillRunning(void);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/partest.h b/gyro_board/src/usb/CommonDemoTasks/include/partest.h
new file mode 100644
index 0000000..4318351
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/partest.h
@@ -0,0 +1,64 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef PARTEST_H
+#define PARTEST_H
+
+#define partstDEFAULT_PORT_ADDRESS		( ( unsigned short ) 0x378 )
+
+void vParTestInitialise(void);
+void vParTestSetLED(unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue);
+void vParTestToggleLED(unsigned portBASE_TYPE uxLED);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/print.h b/gyro_board/src/usb/CommonDemoTasks/include/print.h
new file mode 100644
index 0000000..f0242bd
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/print.h
@@ -0,0 +1,63 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef PRINT_H
+#define PRINT_H
+
+void vPrintInitialise(void);
+void vPrintDisplayMessage(const char * const * pcMessageToSend);
+const char *pcPrintGetNextMessage(portTickType xPrintRate);
+
+#endif
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/recmutex.h b/gyro_board/src/usb/CommonDemoTasks/include/recmutex.h
new file mode 100644
index 0000000..856d6f8
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/recmutex.h
@@ -0,0 +1,61 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef RECURSIVE_MUTEX_TEST_H
+#define RECURSIVE_MUTEX_TEST_H
+
+void vStartRecursiveMutexTasks(void);
+portBASE_TYPE xAreRecursiveMutexTasksStillRunning(void);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/semtest.h b/gyro_board/src/usb/CommonDemoTasks/include/semtest.h
new file mode 100644
index 0000000..04d5369
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/semtest.h
@@ -0,0 +1,61 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef SEMAPHORE_TEST_H
+#define SEMAPHORE_TEST_H
+
+void vStartSemaphoreTasks(unsigned portBASE_TYPE uxPriority);
+portBASE_TYPE xAreSemaphoreTasksStillRunning(void);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/include/serial.h b/gyro_board/src/usb/CommonDemoTasks/include/serial.h
new file mode 100644
index 0000000..dcc76ea
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/include/serial.h
@@ -0,0 +1,119 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef SERIAL_COMMS_H
+#define SERIAL_COMMS_H
+
+typedef void * xComPortHandle;
+
+typedef enum {
+	serCOM1,
+	serCOM2,
+	serCOM3,
+	serCOM4,
+	serCOM5,
+	serCOM6,
+	serCOM7,
+	serCOM8
+} eCOMPort;
+
+typedef enum {
+	serNO_PARITY,
+	serODD_PARITY,
+	serEVEN_PARITY,
+	serMARK_PARITY,
+	serSPACE_PARITY
+} eParity;
+
+typedef enum {
+	serSTOP_1,
+	serSTOP_2
+} eStopBits;
+
+typedef enum {
+	serBITS_5,
+	serBITS_6,
+	serBITS_7,
+	serBITS_8
+} eDataBits;
+
+typedef enum {
+	ser50,
+	ser75,
+	ser110,
+	ser134,
+	ser150,
+	ser200,
+	ser300,
+	ser600,
+	ser1200,
+	ser1800,
+	ser2400,
+	ser4800,
+	ser9600,
+	ser19200,
+	ser38400,
+	ser57600,
+	ser115200
+} eBaud;
+
+xComPortHandle xSerialPortInitMinimal(unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength);
+xComPortHandle xSerialPortInit(eCOMPort ePort, eBaud eWantedBaud, eParity eWantedParity, eDataBits eWantedDataBits, eStopBits eWantedStopBits, unsigned portBASE_TYPE uxBufferLength);
+void vSerialPutString(xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength);
+signed portBASE_TYPE xSerialGetChar(xComPortHandle pxPort, signed char *pcRxedChar, portTickType xBlockTime);
+signed portBASE_TYPE xSerialPutChar(xComPortHandle pxPort, signed char cOutChar, portTickType xBlockTime);
+portBASE_TYPE xSerialWaitForSemaphore(xComPortHandle xPort);
+void vSerialClose(xComPortHandle xPort);
+
+#endif
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/integer.c b/gyro_board/src/usb/CommonDemoTasks/integer.c
new file mode 100644
index 0000000..4e2db69
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/integer.c
@@ -0,0 +1,206 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*
+ * This version of integer. c is for use on systems that have limited stack
+ * space and no display facilities.  The complete version can be found in
+ * the Demo/Common/Full directory.
+ *
+ * As with the full version, the tasks created in this file are a good test
+ * of the scheduler context switch mechanism.  The processor has to access
+ * 32bit variables in two or four chunks (depending on the processor).  The low
+ * priority of these tasks means there is a high probability that a context
+ * switch will occur mid calculation.  See flop. c documentation for
+ * more information.
+ *
+ */
+
+/*
+Changes from V1.2.1
+
+	+ The constants used in the calculations are larger to ensure the
+	  optimiser does not truncate them to 16 bits.
+
+Changes from V1.2.3
+
+	+ uxTaskCheck is now just used as a boolean.  Instead of incrementing
+	  the variable each cycle of the task, the variable is simply set to
+	  true.  sAreIntegerMathsTaskStillRunning() sets it back to false and
+	  expects it to have been set back to true by the time it is called
+	  again.
+	+ A division has been included in the calculation.
+*/
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Demo program include files. */
+#include "integer.h"
+
+/* The constants used in the calculation. */
+#define intgCONST1				( ( long ) 123 )
+#define intgCONST2				( ( long ) 234567 )
+#define intgCONST3				( ( long ) -3 )
+#define intgCONST4				( ( long ) 7 )
+#define intgEXPECTED_ANSWER		( ( ( intgCONST1 + intgCONST2 ) * intgCONST3 ) / intgCONST4 )
+
+#define intgSTACK_SIZE			configMINIMAL_STACK_SIZE
+
+/* As this is the minimal version, we will only create one task. */
+#define intgNUMBER_OF_TASKS		( 1 )
+
+/* The task function.  Repeatedly performs a 32 bit calculation, checking the
+result against the expected result.  If the result is incorrect then the
+context switch must have caused some corruption. */
+static portTASK_FUNCTION_PROTO(vCompeteingIntMathTask, pvParameters);
+
+/* Variables that are set to true within the calculation task to indicate
+that the task is still executing.  The check task sets the variable back to
+false, flagging an error if the variable is still false the next time it
+is called. */
+static volatile signed portBASE_TYPE xTaskCheck[ intgNUMBER_OF_TASKS ] = {(signed portBASE_TYPE) pdFALSE };
+
+/*-----------------------------------------------------------*/
+
+void vStartIntegerMathTasks(unsigned portBASE_TYPE uxPriority)
+{
+	short sTask;
+
+	for (sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++) {
+		xTaskCreate(vCompeteingIntMathTask, (signed char *) "IntMath", intgSTACK_SIZE, (void *) &(xTaskCheck[ sTask ]), uxPriority, (xTaskHandle *) NULL);
+	}
+}
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION(vCompeteingIntMathTask, pvParameters)
+{
+	/* These variables are all effectively set to constants so they are volatile to
+	ensure the compiler does not just get rid of them. */
+	volatile long lValue;
+	short sError = pdFALSE;
+	volatile signed portBASE_TYPE *pxTaskHasExecuted;
+
+	/* Set a pointer to the variable we are going to set to true each
+	iteration.  This is also a good test of the parameter passing mechanism
+	within each port. */
+	pxTaskHasExecuted = (volatile signed portBASE_TYPE *) pvParameters;
+
+	/* Keep performing a calculation and checking the result against a constant. */
+	for (;;) {
+		/* Perform the calculation.  This will store partial value in
+		registers, resulting in a good test of the context switch mechanism. */
+		lValue = intgCONST1;
+		lValue += intgCONST2;
+
+		/* Yield in case cooperative scheduling is being used. */
+#if configUSE_PREEMPTION == 0
+		{
+			taskYIELD();
+		}
+#endif
+
+		/* Finish off the calculation. */
+		lValue *= intgCONST3;
+		lValue /= intgCONST4;
+
+		/* If the calculation is found to be incorrect we stop setting the
+		TaskHasExecuted variable so the check task can see an error has
+		occurred. */
+		if (lValue != intgEXPECTED_ANSWER) { /*lint !e774 volatile used to prevent this being optimised out. */
+			sError = pdTRUE;
+		}
+
+		if (sError == pdFALSE) {
+			/* We have not encountered any errors, so set the flag that show
+			we are still executing.  This will be periodically cleared by
+			the check task. */
+			portENTER_CRITICAL();
+			*pxTaskHasExecuted = pdTRUE;
+			portEXIT_CRITICAL();
+		}
+
+		/* Yield in case cooperative scheduling is being used. */
+#if configUSE_PREEMPTION == 0
+		{
+			taskYIELD();
+		}
+#endif
+	}
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreIntegerMathsTaskStillRunning(void)
+{
+	portBASE_TYPE xReturn = pdTRUE;
+	short sTask;
+
+	/* Check the maths tasks are still running by ensuring their check variables
+	are still being set to true. */
+	for (sTask = 0; sTask < intgNUMBER_OF_TASKS; sTask++) {
+		if (xTaskCheck[ sTask ] == pdFALSE) {
+			/* The check has not incremented so an error exists. */
+			xReturn = pdFALSE;
+		}
+
+		/* Reset the check variable so we can tell if it has been set by
+		the next time around. */
+		xTaskCheck[ sTask ] = pdFALSE;
+	}
+
+	return xReturn;
+}
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/recmutex.c b/gyro_board/src/usb/CommonDemoTasks/recmutex.c
new file mode 100644
index 0000000..9d163d8
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/recmutex.c
@@ -0,0 +1,334 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*
+	The tasks defined on this page demonstrate the use of recursive mutexes.
+
+	For recursive mutex functionality the created mutex should be created using
+	xSemaphoreCreateRecursiveMutex(), then be manipulated
+	using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API
+	functions.
+
+	This demo creates three tasks all of which access the same recursive mutex:
+
+	prvRecursiveMutexControllingTask() has the highest priority so executes
+	first and grabs the mutex.  It then performs some recursive accesses -
+	between each of which it sleeps for a short period to let the lower
+	priority tasks execute.  When it has completed its demo functionality
+	it gives the mutex back before suspending itself.
+
+	prvRecursiveMutexBlockingTask() attempts to access the mutex by performing
+	a blocking 'take'.  The blocking task has a lower priority than the
+	controlling	task so by the time it executes the mutex has already been
+	taken by the controlling task,  causing the blocking task to block.  It
+	does not unblock until the controlling task has given the mutex back,
+	and it does not actually run until the controlling task has suspended
+	itself (due to the relative priorities).  When it eventually does obtain
+	the mutex all it does is give the mutex back prior to also suspending
+	itself.  At this point both the controlling task and the blocking task are
+	suspended.
+
+	prvRecursiveMutexPollingTask() runs at the idle priority.  It spins round
+	a tight loop attempting to obtain the mutex with a non-blocking call.  As
+	the lowest priority task it will not successfully obtain the mutex until
+	both the controlling and blocking tasks are suspended.  Once it eventually
+	does obtain the mutex it first unsuspends both the controlling task and
+	blocking task prior to giving the mutex back - resulting in the polling
+	task temporarily inheriting the controlling tasks priority.
+*/
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Demo app include files. */
+#include "recmutex.h"
+
+/* Priorities assigned to the three tasks. */
+#define recmuCONTROLLING_TASK_PRIORITY	( tskIDLE_PRIORITY + 2 )
+#define recmuBLOCKING_TASK_PRIORITY		( tskIDLE_PRIORITY + 1 )
+#define recmuPOLLING_TASK_PRIORITY		( tskIDLE_PRIORITY + 0 )
+
+/* The recursive call depth. */
+#define recmuMAX_COUNT					( 10 )
+
+/* Misc. */
+#define recmuSHORT_DELAY				( 20 / portTICK_RATE_MS )
+#define recmuNO_DELAY					( ( portTickType ) 0 )
+#define recmuTWO_TICK_DELAY				( ( portTickType ) 2 )
+
+/* The three tasks as described at the top of this file. */
+static void prvRecursiveMutexControllingTask(void *pvParameters);
+static void prvRecursiveMutexBlockingTask(void *pvParameters);
+static void prvRecursiveMutexPollingTask(void *pvParameters);
+
+/* The mutex used by the demo. */
+static xSemaphoreHandle xMutex;
+
+/* Variables used to detect and latch errors. */
+static volatile portBASE_TYPE xErrorOccurred = pdFALSE, xControllingIsSuspended = pdFALSE, xBlockingIsSuspended = pdFALSE;
+static volatile unsigned portBASE_TYPE uxControllingCycles = 0, uxBlockingCycles, uxPollingCycles = 0;
+
+/* Handles of the two higher priority tasks, required so they can be resumed
+(unsuspended). */
+static xTaskHandle xControllingTaskHandle, xBlockingTaskHandle;
+
+/*-----------------------------------------------------------*/
+
+void vStartRecursiveMutexTasks(void)
+{
+	/* Just creates the mutex and the three tasks. */
+
+	xMutex = xSemaphoreCreateRecursiveMutex();
+
+	/* vQueueAddToRegistry() adds the mutex to the registry, if one is
+	in use.  The registry is provided as a means for kernel aware
+	debuggers to locate mutex and has no purpose if a kernel aware debugger
+	is not being used.  The call to vQueueAddToRegistry() will be removed
+	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+	defined to be less than 1. */
+	vQueueAddToRegistry((xQueueHandle) xMutex, (signed portCHAR *) "Recursive_Mutex");
+
+
+	if (xMutex != NULL) {
+		xTaskCreate(prvRecursiveMutexControllingTask, (signed portCHAR *) "Rec1", configMINIMAL_STACK_SIZE, NULL, recmuCONTROLLING_TASK_PRIORITY, &xControllingTaskHandle);
+		xTaskCreate(prvRecursiveMutexBlockingTask, (signed portCHAR *) "Rec2", configMINIMAL_STACK_SIZE, NULL, recmuBLOCKING_TASK_PRIORITY, &xBlockingTaskHandle);
+		xTaskCreate(prvRecursiveMutexPollingTask, (signed portCHAR *) "Rec3", configMINIMAL_STACK_SIZE, NULL, recmuPOLLING_TASK_PRIORITY, NULL);
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexControllingTask(void *pvParameters)
+{
+	unsigned portBASE_TYPE ux;
+
+	/* Just to remove compiler warning. */
+	(void) pvParameters;
+
+	for (;;) {
+		/* Should not be able to 'give' the mutex, as we have not yet 'taken'
+		it. */
+		if (xSemaphoreGiveRecursive(xMutex) == pdPASS) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		for (ux = 0; ux < recmuMAX_COUNT; ux++) {
+			/* We should now be able to take the mutex as many times as
+			we like.  A one tick delay is used so the polling task will
+			inherit our priority on all but the first cycle of this task.
+			If we did not block attempting to receive the mutex then no
+			priority inheritance would occur. */
+			if (xSemaphoreTakeRecursive(xMutex, recmuTWO_TICK_DELAY) != pdPASS) {
+				xErrorOccurred = pdTRUE;
+			}
+
+			/* Ensure the other task attempting to access the mutex (and the
+			other demo tasks) are able to execute. */
+			vTaskDelay(recmuSHORT_DELAY);
+		}
+
+		/* For each time we took the mutex, give it back. */
+		for (ux = 0; ux < recmuMAX_COUNT; ux++) {
+			/* Ensure the other task attempting to access the mutex (and the
+			other demo tasks) are able to execute. */
+			vTaskDelay(recmuSHORT_DELAY);
+
+			/* We should now be able to give the mutex as many times as we
+			took it. */
+			if (xSemaphoreGiveRecursive(xMutex) != pdPASS) {
+				xErrorOccurred = pdTRUE;
+			}
+		}
+
+		/* Having given it back the same number of times as it was taken, we
+		should no longer be the mutex owner, so the next give sh ould fail. */
+		if (xSemaphoreGiveRecursive(xMutex) == pdPASS) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		/* Keep count of the number of cycles this task has performed so a
+		stall can be detected. */
+		uxControllingCycles++;
+
+		/* Suspend ourselves to the blocking task can execute. */
+		xControllingIsSuspended = pdTRUE;
+		vTaskSuspend(NULL);
+		xControllingIsSuspended = pdFALSE;
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexBlockingTask(void *pvParameters)
+{
+	/* Just to remove compiler warning. */
+	(void) pvParameters;
+
+	for (;;) {
+		/* Attempt to obtain the mutex.  We should block until the
+		controlling task has given up the mutex, and not actually execute
+		past this call until the controlling task is suspended. */
+		if (xSemaphoreTakeRecursive(xMutex, portMAX_DELAY) == pdPASS) {
+			if (xControllingIsSuspended != pdTRUE) {
+				/* Did not expect to execute until the controlling task was
+				suspended. */
+				xErrorOccurred = pdTRUE;
+			} else {
+				/* Give the mutex back before suspending ourselves to allow
+				the polling task to obtain the mutex. */
+				if (xSemaphoreGiveRecursive(xMutex) != pdPASS) {
+					xErrorOccurred = pdTRUE;
+				}
+
+				xBlockingIsSuspended = pdTRUE;
+				vTaskSuspend(NULL);
+				xBlockingIsSuspended = pdFALSE;
+			}
+		} else {
+			/* We should not leave the xSemaphoreTakeRecursive() function
+			until the mutex was obtained. */
+			xErrorOccurred = pdTRUE;
+		}
+
+		/* The controlling and blocking tasks should be in lock step. */
+		if (uxControllingCycles != (uxBlockingCycles + 1)) {
+			xErrorOccurred = pdTRUE;
+		}
+
+		/* Keep count of the number of cycles this task has performed so a
+		stall can be detected. */
+		uxBlockingCycles++;
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvRecursiveMutexPollingTask(void *pvParameters)
+{
+	/* Just to remove compiler warning. */
+	(void) pvParameters;
+
+	for (;;) {
+		/* Keep attempting to obtain the mutex.  We should only obtain it when
+		the blocking task has suspended itself. */
+		if (xSemaphoreTakeRecursive(xMutex, recmuNO_DELAY) == pdPASS) {
+			/* Is the blocking task suspended? */
+			if (xBlockingIsSuspended != pdTRUE) {
+				xErrorOccurred = pdTRUE;
+			} else {
+				/* Keep count of the number of cycles this task has performed so
+				a stall can be detected. */
+				uxPollingCycles++;
+
+				/* We can resume the other tasks here even though they have a
+				higher priority than the polling task.  When they execute they
+				will attempt to obtain the mutex but fail because the polling
+				task is still the mutex holder.  The polling task (this task)
+				will then inherit the higher priority. */
+				vTaskResume(xBlockingTaskHandle);
+				vTaskResume(xControllingTaskHandle);
+
+				/* Release the mutex, disinheriting the higher priority again. */
+				if (xSemaphoreGiveRecursive(xMutex) != pdPASS) {
+					xErrorOccurred = pdTRUE;
+				}
+			}
+		}
+
+#if configUSE_PREEMPTION == 0
+		{
+			taskYIELD();
+		}
+#endif
+	}
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreRecursiveMutexTasksStillRunning(void)
+{
+	portBASE_TYPE xReturn;
+	static unsigned portBASE_TYPE uxLastControllingCycles = 0, uxLastBlockingCycles = 0, uxLastPollingCycles = 0;
+
+	/* Is the controlling task still cycling? */
+	if (uxLastControllingCycles == uxControllingCycles) {
+		xErrorOccurred = pdTRUE;
+	} else {
+		uxLastControllingCycles = uxControllingCycles;
+	}
+
+	/* Is the blocking task still cycling? */
+	if (uxLastBlockingCycles == uxBlockingCycles) {
+		xErrorOccurred = pdTRUE;
+	} else {
+		uxLastBlockingCycles = uxBlockingCycles;
+	}
+
+	/* Is the polling task still cycling? */
+	if (uxLastPollingCycles == uxPollingCycles) {
+		xErrorOccurred = pdTRUE;
+	} else {
+		uxLastPollingCycles = uxPollingCycles;
+	}
+
+	if (xErrorOccurred == pdTRUE) {
+		xReturn = pdFAIL;
+	} else {
+		xReturn = pdTRUE;
+	}
+
+	return xReturn;
+}
+
+
+
+
diff --git a/gyro_board/src/usb/CommonDemoTasks/semtest.c b/gyro_board/src/usb/CommonDemoTasks/semtest.c
new file mode 100644
index 0000000..055ed11
--- /dev/null
+++ b/gyro_board/src/usb/CommonDemoTasks/semtest.c
@@ -0,0 +1,263 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*
+ * Creates two sets of two tasks.  The tasks within a set share a variable, access
+ * to which is guarded by a semaphore.
+ *
+ * Each task starts by attempting to obtain the semaphore.  On obtaining a
+ * semaphore a task checks to ensure that the guarded variable has an expected
+ * value.  It then clears the variable to zero before counting it back up to the
+ * expected value in increments of 1.  After each increment the variable is checked
+ * to ensure it contains the value to which it was just set. When the starting
+ * value is again reached the task releases the semaphore giving the other task in
+ * the set a chance to do exactly the same thing.  The starting value is high
+ * enough to ensure that a tick is likely to occur during the incrementing loop.
+ *
+ * An error is flagged if at any time during the process a shared variable is
+ * found to have a value other than that expected.  Such an occurrence would
+ * suggest an error in the mutual exclusion mechanism by which access to the
+ * variable is restricted.
+ *
+ * The first set of two tasks poll their semaphore.  The second set use blocking
+ * calls.
+ *
+ */
+
+
+#include <stdlib.h>
+
+/* Scheduler include files. */
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+/* Demo app include files. */
+#include "semtest.h"
+
+/* The value to which the shared variables are counted. */
+#define semtstBLOCKING_EXPECTED_VALUE		( ( unsigned long ) 0xfff )
+#define semtstNON_BLOCKING_EXPECTED_VALUE	( ( unsigned long ) 0xff  )
+
+#define semtstSTACK_SIZE			configMINIMAL_STACK_SIZE
+
+#define semtstNUM_TASKS				( 4 )
+
+#define semtstDELAY_FACTOR			( ( portTickType ) 10 )
+
+/* The task function as described at the top of the file. */
+static portTASK_FUNCTION_PROTO(prvSemaphoreTest, pvParameters);
+
+/* Structure used to pass parameters to each task. */
+typedef struct SEMAPHORE_PARAMETERS {
+	xSemaphoreHandle xSemaphore;
+	volatile unsigned long *pulSharedVariable;
+	portTickType xBlockTime;
+} xSemaphoreParameters;
+
+/* Variables used to check that all the tasks are still running without errors. */
+static volatile short sCheckVariables[ semtstNUM_TASKS ] = { 0 };
+static volatile short sNextCheckVariable = 0;
+
+/*-----------------------------------------------------------*/
+
+void vStartSemaphoreTasks(unsigned portBASE_TYPE uxPriority)
+{
+	xSemaphoreParameters *pxFirstSemaphoreParameters, *pxSecondSemaphoreParameters;
+	const portTickType xBlockTime = (portTickType) 100;
+
+	/* Create the structure used to pass parameters to the first two tasks. */
+	pxFirstSemaphoreParameters = (xSemaphoreParameters *) pvPortMalloc(sizeof(xSemaphoreParameters));
+
+	if (pxFirstSemaphoreParameters != NULL) {
+		/* Create the semaphore used by the first two tasks. */
+		vSemaphoreCreateBinary(pxFirstSemaphoreParameters->xSemaphore);
+
+		if (pxFirstSemaphoreParameters->xSemaphore != NULL) {
+			/* Create the variable which is to be shared by the first two tasks. */
+			pxFirstSemaphoreParameters->pulSharedVariable = (unsigned long *) pvPortMalloc(sizeof(unsigned long));
+
+			/* Initialise the share variable to the value the tasks expect. */
+			*(pxFirstSemaphoreParameters->pulSharedVariable) = semtstNON_BLOCKING_EXPECTED_VALUE;
+
+			/* The first two tasks do not block on semaphore calls. */
+			pxFirstSemaphoreParameters->xBlockTime = (portTickType) 0;
+
+			/* Spawn the first two tasks.  As they poll they operate at the idle priority. */
+			xTaskCreate(prvSemaphoreTest, (signed char *) "PolSEM1", semtstSTACK_SIZE, (void *) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, (xTaskHandle *) NULL);
+			xTaskCreate(prvSemaphoreTest, (signed char *) "PolSEM2", semtstSTACK_SIZE, (void *) pxFirstSemaphoreParameters, tskIDLE_PRIORITY, (xTaskHandle *) NULL);
+		}
+	}
+
+	/* Do exactly the same to create the second set of tasks, only this time
+	provide a block time for the semaphore calls. */
+	pxSecondSemaphoreParameters = (xSemaphoreParameters *) pvPortMalloc(sizeof(xSemaphoreParameters));
+	if (pxSecondSemaphoreParameters != NULL) {
+		vSemaphoreCreateBinary(pxSecondSemaphoreParameters->xSemaphore);
+
+		if (pxSecondSemaphoreParameters->xSemaphore != NULL) {
+			pxSecondSemaphoreParameters->pulSharedVariable = (unsigned long *) pvPortMalloc(sizeof(unsigned long));
+			*(pxSecondSemaphoreParameters->pulSharedVariable) = semtstBLOCKING_EXPECTED_VALUE;
+			pxSecondSemaphoreParameters->xBlockTime = xBlockTime / portTICK_RATE_MS;
+
+			xTaskCreate(prvSemaphoreTest, (signed char *) "BlkSEM1", semtstSTACK_SIZE, (void *) pxSecondSemaphoreParameters, uxPriority, (xTaskHandle *) NULL);
+			xTaskCreate(prvSemaphoreTest, (signed char *) "BlkSEM2", semtstSTACK_SIZE, (void *) pxSecondSemaphoreParameters, uxPriority, (xTaskHandle *) NULL);
+		}
+	}
+
+	/* vQueueAddToRegistry() adds the semaphore to the registry, if one is
+	in use.  The registry is provided as a means for kernel aware
+	debuggers to locate semaphores and has no purpose if a kernel aware debugger
+	is not being used.  The call to vQueueAddToRegistry() will be removed
+	by the pre-processor if configQUEUE_REGISTRY_SIZE is not defined or is
+	defined to be less than 1. */
+	vQueueAddToRegistry((xQueueHandle) pxFirstSemaphoreParameters->xSemaphore, (signed char *) "Counting_Sem_1");
+	vQueueAddToRegistry((xQueueHandle) pxSecondSemaphoreParameters->xSemaphore, (signed char *) "Counting_Sem_2");
+}
+/*-----------------------------------------------------------*/
+
+static portTASK_FUNCTION(prvSemaphoreTest, pvParameters)
+{
+	xSemaphoreParameters *pxParameters;
+	volatile unsigned long *pulSharedVariable, ulExpectedValue;
+	unsigned long ulCounter;
+	short sError = pdFALSE, sCheckVariableToUse;
+
+	/* See which check variable to use.  sNextCheckVariable is not semaphore
+	protected! */
+	portENTER_CRITICAL();
+	sCheckVariableToUse = sNextCheckVariable;
+	sNextCheckVariable++;
+	portEXIT_CRITICAL();
+
+	/* A structure is passed in as the parameter.  This contains the shared
+	variable being guarded. */
+	pxParameters = (xSemaphoreParameters *) pvParameters;
+	pulSharedVariable = pxParameters->pulSharedVariable;
+
+	/* If we are blocking we use a much higher count to ensure loads of context
+	switches occur during the count. */
+	if (pxParameters->xBlockTime > (portTickType) 0) {
+		ulExpectedValue = semtstBLOCKING_EXPECTED_VALUE;
+	} else {
+		ulExpectedValue = semtstNON_BLOCKING_EXPECTED_VALUE;
+	}
+
+	for (;;) {
+		/* Try to obtain the semaphore. */
+		if (xSemaphoreTake(pxParameters->xSemaphore, pxParameters->xBlockTime) == pdPASS) {
+			/* We have the semaphore and so expect any other tasks using the
+			shared variable to have left it in the state we expect to find
+			it. */
+			if (*pulSharedVariable != ulExpectedValue) {
+				sError = pdTRUE;
+			}
+
+			/* Clear the variable, then count it back up to the expected value
+			before releasing the semaphore.  Would expect a context switch or
+			two during this time. */
+			for (ulCounter = (unsigned long) 0; ulCounter <= ulExpectedValue; ulCounter++) {
+				*pulSharedVariable = ulCounter;
+				if (*pulSharedVariable != ulCounter) {
+					sError = pdTRUE;
+				}
+			}
+
+			/* Release the semaphore, and if no errors have occurred increment the check
+			variable. */
+			if (xSemaphoreGive(pxParameters->xSemaphore) == pdFALSE) {
+				sError = pdTRUE;
+			}
+
+			if (sError == pdFALSE) {
+				if (sCheckVariableToUse < semtstNUM_TASKS) {
+					(sCheckVariables[ sCheckVariableToUse ])++;
+				}
+			}
+
+			/* If we have a block time then we are running at a priority higher
+			than the idle priority.  This task takes a long time to complete
+			a cycle	(deliberately so to test the guarding) so will be starving
+			out lower priority tasks.  Block for some time to allow give lower
+			priority tasks some processor time. */
+			vTaskDelay(pxParameters->xBlockTime * semtstDELAY_FACTOR);
+		} else {
+			if (pxParameters->xBlockTime == (portTickType) 0) {
+				/* We have not got the semaphore yet, so no point using the
+				processor.  We are not blocking when attempting to obtain the
+				semaphore. */
+				taskYIELD();
+			}
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+/* This is called to check that all the created tasks are still running. */
+portBASE_TYPE xAreSemaphoreTasksStillRunning(void)
+{
+	static short sLastCheckVariables[ semtstNUM_TASKS ] = { 0 };
+	portBASE_TYPE xTask, xReturn = pdTRUE;
+
+	for (xTask = 0; xTask < semtstNUM_TASKS; xTask++) {
+		if (sLastCheckVariables[ xTask ] == sCheckVariables[ xTask ]) {
+			xReturn = pdFALSE;
+		}
+
+		sLastCheckVariables[ xTask ] = sCheckVariables[ xTask ];
+	}
+
+	return xReturn;
+}
+
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/FreeRTOS.h b/gyro_board/src/usb/FreeRTOS/include/FreeRTOS.h
new file mode 100644
index 0000000..afbd505
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/FreeRTOS.h
@@ -0,0 +1,420 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef INC_FREERTOS_H
+#define INC_FREERTOS_H
+
+
+/*
+ * Include the generic headers required for the FreeRTOS port being used.
+ */
+#include <stddef.h>
+
+/* Basic FreeRTOS definitions. */
+#include "projdefs.h"
+
+/* Application specific configuration options. */
+#include "FreeRTOSConfig.h"
+
+/* Definitions specific to the port being used. */
+#include "portable.h"
+
+
+/* Defines the prototype to which the application task hook function must
+conform. */
+typedef portBASE_TYPE(*pdTASK_HOOK_CODE)(void *);
+
+
+
+
+
+/*
+ * Check all the required application specific macros have been defined.
+ * These macros are application specific and (as downloaded) are defined
+ * within FreeRTOSConfig.h.
+ */
+
+#ifndef configUSE_PREEMPTION
+#error Missing definition:  configUSE_PREEMPTION should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_IDLE_HOOK
+#error Missing definition:  configUSE_IDLE_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_TICK_HOOK
+#error Missing definition:  configUSE_TICK_HOOK should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_CO_ROUTINES
+#error  Missing definition:  configUSE_CO_ROUTINES should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskPrioritySet
+#error Missing definition:  INCLUDE_vTaskPrioritySet should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_uxTaskPriorityGet
+#error Missing definition:  INCLUDE_uxTaskPriorityGet should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelete
+#error Missing definition:  INCLUDE_vTaskDelete		 should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskCleanUpResources
+#error Missing definition:  INCLUDE_vTaskCleanUpResources should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskSuspend
+#error Missing definition:  INCLUDE_vTaskSuspend	 should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelayUntil
+#error Missing definition:  INCLUDE_vTaskDelayUntil should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef INCLUDE_vTaskDelay
+#error Missing definition:  INCLUDE_vTaskDelay should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_16_BIT_TICKS
+#error Missing definition:  configUSE_16_BIT_TICKS should be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.
+#endif
+
+#ifndef configUSE_APPLICATION_TASK_TAG
+#define configUSE_APPLICATION_TASK_TAG 0
+#endif
+
+#ifndef INCLUDE_uxTaskGetStackHighWaterMark
+#define INCLUDE_uxTaskGetStackHighWaterMark 0
+#endif
+
+#ifndef configUSE_RECURSIVE_MUTEXES
+#define configUSE_RECURSIVE_MUTEXES 0
+#endif
+
+#ifndef configUSE_MUTEXES
+#define configUSE_MUTEXES 0
+#endif
+
+#ifndef configUSE_COUNTING_SEMAPHORES
+#define configUSE_COUNTING_SEMAPHORES 0
+#endif
+
+#ifndef configUSE_ALTERNATIVE_API
+#define configUSE_ALTERNATIVE_API 0
+#endif
+
+#ifndef portCRITICAL_NESTING_IN_TCB
+#define portCRITICAL_NESTING_IN_TCB 0
+#endif
+
+#ifndef configMAX_TASK_NAME_LEN
+#define configMAX_TASK_NAME_LEN 16
+#endif
+
+#ifndef configIDLE_SHOULD_YIELD
+#define configIDLE_SHOULD_YIELD		1
+#endif
+
+#if configMAX_TASK_NAME_LEN < 1
+#undef configMAX_TASK_NAME_LEN
+#define configMAX_TASK_NAME_LEN 1
+#endif
+
+#ifndef INCLUDE_xTaskResumeFromISR
+#define INCLUDE_xTaskResumeFromISR 1
+#endif
+
+#ifndef INCLUDE_xTaskGetSchedulerState
+#define INCLUDE_xTaskGetSchedulerState 0
+#endif
+
+#if ( configUSE_MUTEXES == 1 )
+/* xTaskGetCurrentTaskHandle is used by the priority inheritance mechanism
+within the mutex implementation so must be available if mutexes are used. */
+#undef INCLUDE_xTaskGetCurrentTaskHandle
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#else
+#ifndef INCLUDE_xTaskGetCurrentTaskHandle
+#define INCLUDE_xTaskGetCurrentTaskHandle 0
+#endif
+#endif
+
+
+#ifndef portSET_INTERRUPT_MASK_FROM_ISR
+#define portSET_INTERRUPT_MASK_FROM_ISR() 0
+#endif
+
+#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
+#endif
+
+
+#ifndef configQUEUE_REGISTRY_SIZE
+#define configQUEUE_REGISTRY_SIZE 0
+#endif
+
+#if configQUEUE_REGISTRY_SIZE < 1
+#define configQUEUE_REGISTRY_SIZE 0
+#define vQueueAddToRegistry( xQueue, pcName )
+#define vQueueUnregisterQueue( xQueue )
+#endif
+
+
+/* Remove any unused trace macros. */
+#ifndef traceSTART
+/* Used to perform any necessary initialisation - for example, open a file
+into which trace is to be written. */
+#define traceSTART()
+#endif
+
+#ifndef traceEND
+/* Use to close a trace, for example close a file into which trace has been
+written. */
+#define traceEND()
+#endif
+
+#ifndef traceTASK_SWITCHED_IN
+/* Called after a task has been selected to run.  pxCurrentTCB holds a pointer
+to the task control block of the selected task. */
+#define traceTASK_SWITCHED_IN()
+#endif
+
+#ifndef traceTASK_SWITCHED_OUT
+/* Called before a task has been selected to run.  pxCurrentTCB holds a pointer
+to the task control block of the task being switched out. */
+#define traceTASK_SWITCHED_OUT()
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_RECEIVE
+/* Task is about to block because it cannot read from a
+queue/mutex/semaphore.  pxQueue is a pointer to the queue/mutex/semaphore
+upon which the read was attempted.  pxCurrentTCB points to the TCB of the
+task that attempted the read. */
+#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue )
+#endif
+
+#ifndef traceBLOCKING_ON_QUEUE_SEND
+/* Task is about to block because it cannot write to a
+queue/mutex/semaphore.  pxQueue is a pointer to the queue/mutex/semaphore
+upon which the write was attempted.  pxCurrentTCB points to the TCB of the
+task that attempted the write. */
+#define traceBLOCKING_ON_QUEUE_SEND( pxQueue )
+#endif
+
+#ifndef configCHECK_FOR_STACK_OVERFLOW
+#define configCHECK_FOR_STACK_OVERFLOW 0
+#endif
+
+/* The following event macros are embedded in the kernel API calls. */
+
+#ifndef traceQUEUE_CREATE
+#define traceQUEUE_CREATE( pxNewQueue )
+#endif
+
+#ifndef traceQUEUE_CREATE_FAILED
+#define traceQUEUE_CREATE_FAILED()
+#endif
+
+#ifndef traceCREATE_MUTEX
+#define traceCREATE_MUTEX( pxNewQueue )
+#endif
+
+#ifndef traceCREATE_MUTEX_FAILED
+#define traceCREATE_MUTEX_FAILED()
+#endif
+
+#ifndef traceGIVE_MUTEX_RECURSIVE
+#define traceGIVE_MUTEX_RECURSIVE( pxMutex )
+#endif
+
+#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED
+#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex )
+#endif
+
+#ifndef traceTAKE_MUTEX_RECURSIVE
+#define traceTAKE_MUTEX_RECURSIVE( pxMutex )
+#endif
+
+#ifndef traceCREATE_COUNTING_SEMAPHORE
+#define traceCREATE_COUNTING_SEMAPHORE()
+#endif
+
+#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED
+#define traceCREATE_COUNTING_SEMAPHORE_FAILED()
+#endif
+
+#ifndef traceQUEUE_SEND
+#define traceQUEUE_SEND( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FAILED
+#define traceQUEUE_SEND_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE
+#define traceQUEUE_RECEIVE( pxQueue )
+#endif
+
+#ifndef traceQUEUE_PEEK
+#define traceQUEUE_PEEK( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FAILED
+#define traceQUEUE_RECEIVE_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FROM_ISR
+#define traceQUEUE_SEND_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_SEND_FROM_ISR_FAILED
+#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FROM_ISR
+#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue )
+#endif
+
+#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED
+#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue )
+#endif
+
+#ifndef traceQUEUE_DELETE
+#define traceQUEUE_DELETE( pxQueue )
+#endif
+
+#ifndef traceTASK_CREATE
+#define traceTASK_CREATE( pxNewTCB )
+#endif
+
+#ifndef traceTASK_CREATE_FAILED
+#define traceTASK_CREATE_FAILED( pxNewTCB )
+#endif
+
+#ifndef traceTASK_DELETE
+#define traceTASK_DELETE( pxTaskToDelete )
+#endif
+
+#ifndef traceTASK_DELAY_UNTIL
+#define traceTASK_DELAY_UNTIL()
+#endif
+
+#ifndef traceTASK_DELAY
+#define traceTASK_DELAY()
+#endif
+
+#ifndef traceTASK_PRIORITY_SET
+#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority )
+#endif
+
+#ifndef traceTASK_SUSPEND
+#define traceTASK_SUSPEND( pxTaskToSuspend )
+#endif
+
+#ifndef traceTASK_RESUME
+#define traceTASK_RESUME( pxTaskToResume )
+#endif
+
+#ifndef traceTASK_RESUME_FROM_ISR
+#define traceTASK_RESUME_FROM_ISR( pxTaskToResume )
+#endif
+
+#ifndef traceTASK_INCREMENT_TICK
+#define traceTASK_INCREMENT_TICK( xTickCount )
+#endif
+
+#ifndef configGENERATE_RUN_TIME_STATS
+#define configGENERATE_RUN_TIME_STATS 0
+#endif
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
+#error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined.  portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base.
+#endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */
+
+#ifndef portGET_RUN_TIME_COUNTER_VALUE
+#error If configGENERATE_RUN_TIME_STATS is defined then portGET_RUN_TIME_COUNTER_VALUE must also be defined.  portGET_RUN_TIME_COUNTER_VALUE should evaluate to the counter value of the timer/counter peripheral used as the run time counter time base.
+#endif /* portGET_RUN_TIME_COUNTER_VALUE */
+
+#endif /* configGENERATE_RUN_TIME_STATS */
+
+#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
+#endif
+
+#ifndef configUSE_MALLOC_FAILED_HOOK
+#define configUSE_MALLOC_FAILED_HOOK 0
+#endif
+
+#ifndef portPRIVILEGE_BIT
+#define portPRIVILEGE_BIT ( ( unsigned portBASE_TYPE ) 0x00 )
+#endif
+
+#ifndef portYIELD_WITHIN_API
+#define portYIELD_WITHIN_API portYIELD
+#endif
+
+#ifndef pvPortMallocAligned
+#define pvPortMallocAligned( x, puxStackBuffer ) ( ( puxStackBuffer == NULL ) ? ( pvPortMalloc( x ) ) : ( puxStackBuffer ) )
+#endif
+
+#ifndef vPortFreeAligned
+#define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree )
+#endif
+
+#endif /* INC_FREERTOS_H */
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/StackMacros.h b/gyro_board/src/usb/FreeRTOS/include/StackMacros.h
new file mode 100644
index 0000000..67d4c09
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/StackMacros.h
@@ -0,0 +1,173 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef STACK_MACROS_H
+#define STACK_MACROS_H
+
+/*
+ * Call the stack overflow hook function if the stack of the task being swapped
+ * out is currently overflowed, or looks like it might have overflowed in the
+ * past.
+ *
+ * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
+ * the current stack state only - comparing the current top of stack value to
+ * the stack limit.  Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
+ * will also cause the last few stack bytes to be checked to ensure the value
+ * to which the bytes were set when the task was created have not been
+ * overwritten.  Note this second test does not guarantee that an overflowed
+ * stack will always be recognised.
+ */
+
+/*-----------------------------------------------------------*/
+
+#if( configCHECK_FOR_STACK_OVERFLOW == 0 )
+
+/* FreeRTOSConfig.h is not set to check for stack overflows. */
+#define taskFIRST_CHECK_FOR_STACK_OVERFLOW()
+#define taskSECOND_CHECK_FOR_STACK_OVERFLOW()
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 0 */
+/*-----------------------------------------------------------*/
+
+#if( configCHECK_FOR_STACK_OVERFLOW == 1 )
+
+/* FreeRTOSConfig.h is only set to use the first method of
+overflow checking. */
+#define taskSECOND_CHECK_FOR_STACK_OVERFLOW()
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH < 0 ) )
+
+/* Only the current stack state is to be checked. */
+#define taskFIRST_CHECK_FOR_STACK_OVERFLOW()														\
+	{																									\
+	extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName );			\
+																										\
+		/* Is the currently saved stack pointer within the stack limit? */								\
+		if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack )										\
+		{																								\
+			vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName );	\
+		}																								\
+	}
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW > 0 */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 0 ) && ( portSTACK_GROWTH > 0 ) )
+
+/* Only the current stack state is to be checked. */
+#define taskFIRST_CHECK_FOR_STACK_OVERFLOW()														\
+	{																									\
+	extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName );		\
+																										\
+		/* Is the currently saved stack pointer within the stack limit? */								\
+		if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack )									\
+		{																								\
+			vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName );	\
+		}																								\
+	}
+
+#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
+
+#define taskSECOND_CHECK_FOR_STACK_OVERFLOW()																									\
+	{																																				\
+	extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName );													\
+	static const unsigned char ucExpectedStackBytes[] = {	tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+																tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+																tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+																tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+																tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE };	\
+																																					\
+																																					\
+		/* Has the extremity of the task stack ever been written over? */																			\
+		if( memcmp( ( void * ) pxCurrentTCB->pxStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 )						\
+		{																																			\
+			vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName );												\
+		}																																			\
+	}
+
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
+/*-----------------------------------------------------------*/
+
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
+
+#define taskSECOND_CHECK_FOR_STACK_OVERFLOW()																									\
+	{																																				\
+	extern void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName );													\
+	char *pcEndOfStack = ( char * ) pxCurrentTCB->pxEndOfStack;																				\
+	static const unsigned char ucExpectedStackBytes[] = {	tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+																tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+																tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+																tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE,		\
+																tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE };	\
+																																					\
+																																					\
+		pcEndOfStack -= sizeof( ucExpectedStackBytes );																								\
+																																					\
+		/* Has the extremity of the task stack ever been written over? */																			\
+		if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 )								\
+		{																																			\
+			vApplicationStackOverflowHook( ( xTaskHandle ) pxCurrentTCB, pxCurrentTCB->pcTaskName );												\
+		}																																			\
+	}
+
+#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
+/*-----------------------------------------------------------*/
+
+#endif /* STACK_MACROS_H */
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/croutine.h b/gyro_board/src/usb/FreeRTOS/include/croutine.h
new file mode 100644
index 0000000..bcedb26
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/croutine.h
@@ -0,0 +1,749 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef INC_FREERTOS_H
+#error "#include FreeRTOS.h" must appear in source files before "#include croutine.h"
+#endif
+
+
+
+
+#ifndef CO_ROUTINE_H
+#define CO_ROUTINE_H
+
+#include "list.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	/* Used to hide the implementation of the co-routine control block.  The
+	control block structure however has to be included in the header due to
+	the macro implementation of the co-routine functionality. */
+	typedef void * xCoRoutineHandle;
+
+	/* Defines the prototype to which co-routine functions must conform. */
+	typedef void (*crCOROUTINE_CODE)(xCoRoutineHandle, unsigned portBASE_TYPE);
+
+	typedef struct corCoRoutineControlBlock {
+		crCOROUTINE_CODE 		pxCoRoutineFunction;
+		xListItem				xGenericListItem;	/*< List item used to place the CRCB in ready and blocked queues. */
+		xListItem				xEventListItem;		/*< List item used to place the CRCB in event lists. */
+		unsigned portBASE_TYPE 	uxPriority;			/*< The priority of the co-routine in relation to other co-routines. */
+		unsigned portBASE_TYPE 	uxIndex;			/*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
+		unsigned short 		uxState;			/*< Used internally by the co-routine implementation. */
+	} corCRCB; /* Co-routine control block.  Note must be identical in size down to uxPriority with tskTCB. */
+
+	/**
+	 * croutine. h
+	 *<pre>
+	 portBASE_TYPE xCoRoutineCreate(
+	                                 crCOROUTINE_CODE pxCoRoutineCode,
+	                                 unsigned portBASE_TYPE uxPriority,
+	                                 unsigned portBASE_TYPE uxIndex
+	                               );</pre>
+	 *
+	 * Create a new co-routine and add it to the list of co-routines that are
+	 * ready to run.
+	 *
+	 * @param pxCoRoutineCode Pointer to the co-routine function.  Co-routine
+	 * functions require special syntax - see the co-routine section of the WEB
+	 * documentation for more information.
+	 *
+	 * @param uxPriority The priority with respect to other co-routines at which
+	 *  the co-routine will run.
+	 *
+	 * @param uxIndex Used to distinguish between different co-routines that
+	 * execute the same function.  See the example below and the co-routine section
+	 * of the WEB documentation for further information.
+	 *
+	 * @return pdPASS if the co-routine was successfully created and added to a ready
+	 * list, otherwise an error code defined with ProjDefs.h.
+	 *
+	 * Example usage:
+	   <pre>
+	 // Co-routine to be created.
+	 void vFlashCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+	 {
+	 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+	 // This may not be necessary for const variables.
+	 static const char cLedToFlash[ 2 ] = { 5, 6 };
+	 static const portTickType uxFlashRates[ 2 ] = { 200, 400 };
+
+	     // Must start every co-routine with a call to crSTART();
+	     crSTART( xHandle );
+
+	     for( ;; )
+	     {
+	         // This co-routine just delays for a fixed period, then toggles
+	         // an LED.  Two co-routines are created using this function, so
+	         // the uxIndex parameter is used to tell the co-routine which
+	         // LED to flash and how long to delay.  This assumes xQueue has
+	         // already been created.
+	         vParTestToggleLED( cLedToFlash[ uxIndex ] );
+	         crDELAY( xHandle, uxFlashRates[ uxIndex ] );
+	     }
+
+	     // Must end every co-routine with a call to crEND();
+	     crEND();
+	 }
+
+	 // Function that creates two co-routines.
+	 void vOtherFunction( void )
+	 {
+	 unsigned char ucParameterToPass;
+	 xTaskHandle xHandle;
+
+	     // Create two co-routines at priority 0.  The first is given index 0
+	     // so (from the code above) toggles LED 5 every 200 ticks.  The second
+	     // is given index 1 so toggles LED 6 every 400 ticks.
+	     for( uxIndex = 0; uxIndex < 2; uxIndex++ )
+	     {
+	         xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
+	     }
+	 }
+	   </pre>
+	 * \defgroup xCoRoutineCreate xCoRoutineCreate
+	 * \ingroup Tasks
+	 */
+	signed portBASE_TYPE xCoRoutineCreate(crCOROUTINE_CODE pxCoRoutineCode, unsigned portBASE_TYPE uxPriority, unsigned portBASE_TYPE uxIndex);
+
+
+	/**
+	 * croutine. h
+	 *<pre>
+	 void vCoRoutineSchedule( void );</pre>
+	 *
+	 * Run a co-routine.
+	 *
+	 * vCoRoutineSchedule() executes the highest priority co-routine that is able
+	 * to run.  The co-routine will execute until it either blocks, yields or is
+	 * preempted by a task.  Co-routines execute cooperatively so one
+	 * co-routine cannot be preempted by another, but can be preempted by a task.
+	 *
+	 * If an application comprises of both tasks and co-routines then
+	 * vCoRoutineSchedule should be called from the idle task (in an idle task
+	 * hook).
+	 *
+	 * Example usage:
+	   <pre>
+	 // This idle task hook will schedule a co-routine each time it is called.
+	 // The rest of the idle task will execute between co-routine calls.
+	 void vApplicationIdleHook( void )
+	 {
+		vCoRoutineSchedule();
+	 }
+
+	 // Alternatively, if you do not require any other part of the idle task to
+	 // execute, the idle task hook can call vCoRoutineScheduler() within an
+	 // infinite loop.
+	 void vApplicationIdleHook( void )
+	 {
+	    for( ;; )
+	    {
+	        vCoRoutineSchedule();
+	    }
+	 }
+	 </pre>
+	 * \defgroup vCoRoutineSchedule vCoRoutineSchedule
+	 * \ingroup Tasks
+	 */
+	void vCoRoutineSchedule(void);
+
+	/**
+	 * croutine. h
+	 * <pre>
+	 crSTART( xCoRoutineHandle xHandle );</pre>
+	 *
+	 * This macro MUST always be called at the start of a co-routine function.
+	 *
+	 * Example usage:
+	   <pre>
+	 // Co-routine to be created.
+	 void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+	 {
+	 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+	 static long ulAVariable;
+
+	     // Must start every co-routine with a call to crSTART();
+	     crSTART( xHandle );
+
+	     for( ;; )
+	     {
+	          // Co-routine functionality goes here.
+	     }
+
+	     // Must end every co-routine with a call to crEND();
+	     crEND();
+	 }</pre>
+	 * \defgroup crSTART crSTART
+	 * \ingroup Tasks
+	 */
+#define crSTART( pxCRCB ) switch( ( ( corCRCB * )pxCRCB )->uxState ) { case 0:
+
+	/**
+	 * croutine. h
+	 * <pre>
+	 crEND();</pre>
+	 *
+	 * This macro MUST always be called at the end of a co-routine function.
+	 *
+	 * Example usage:
+	   <pre>
+	 // Co-routine to be created.
+	 void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+	 {
+	 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+	 static long ulAVariable;
+
+	     // Must start every co-routine with a call to crSTART();
+	     crSTART( xHandle );
+
+	     for( ;; )
+	     {
+	          // Co-routine functionality goes here.
+	     }
+
+	     // Must end every co-routine with a call to crEND();
+	     crEND();
+	 }</pre>
+	 * \defgroup crSTART crSTART
+	 * \ingroup Tasks
+	 */
+#define crEND() }
+
+	/*
+	 * These macros are intended for internal use by the co-routine implementation
+	 * only.  The macros should not be used directly by application writers.
+	 */
+#define crSET_STATE0( xHandle ) ( ( corCRCB * )xHandle)->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
+#define crSET_STATE1( xHandle ) ( ( corCRCB * )xHandle)->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
+
+	/**
+	 * croutine. h
+	 *<pre>
+	 crDELAY( xCoRoutineHandle xHandle, portTickType xTicksToDelay );</pre>
+	 *
+	 * Delay a co-routine for a fixed period of time.
+	 *
+	 * crDELAY can only be called from the co-routine function itself - not
+	 * from within a function called by the co-routine function.  This is because
+	 * co-routines do not maintain their own stack.
+	 *
+	 * @param xHandle The handle of the co-routine to delay.  This is the xHandle
+	 * parameter of the co-routine function.
+	 *
+	 * @param xTickToDelay The number of ticks that the co-routine should delay
+	 * for.  The actual amount of time this equates to is defined by
+	 * configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant portTICK_RATE_MS
+	 * can be used to convert ticks to milliseconds.
+	 *
+	 * Example usage:
+	   <pre>
+	 // Co-routine to be created.
+	 void vACoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+	 {
+	 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+	 // This may not be necessary for const variables.
+	 // We are to delay for 200ms.
+	 static const xTickType xDelayTime = 200 / portTICK_RATE_MS;
+
+	     // Must start every co-routine with a call to crSTART();
+	     crSTART( xHandle );
+
+	     for( ;; )
+	     {
+	        // Delay for 200ms.
+	        crDELAY( xHandle, xDelayTime );
+
+	        // Do something here.
+	     }
+
+	     // Must end every co-routine with a call to crEND();
+	     crEND();
+	 }</pre>
+	 * \defgroup crDELAY crDELAY
+	 * \ingroup Tasks
+	 */
+#define crDELAY( xHandle, xTicksToDelay )												\
+	if( xTicksToDelay > 0 )																\
+	{																					\
+		vCoRoutineAddToDelayedList( xTicksToDelay, NULL );								\
+	}																					\
+	crSET_STATE0( xHandle );
+
+	/**
+	 * <pre>
+	 crQUEUE_SEND(
+	                  xCoRoutineHandle xHandle,
+	                  xQueueHandle pxQueue,
+	                  void *pvItemToQueue,
+	                  portTickType xTicksToWait,
+	                  portBASE_TYPE *pxResult
+	             )</pre>
+	 *
+	 * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
+	 * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
+	 *
+	 * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
+	 * xQueueSend() and xQueueReceive() can only be used from tasks.
+	 *
+	 * crQUEUE_SEND can only be called from the co-routine function itself - not
+	 * from within a function called by the co-routine function.  This is because
+	 * co-routines do not maintain their own stack.
+	 *
+	 * See the co-routine section of the WEB documentation for information on
+	 * passing data between tasks and co-routines and between ISR's and
+	 * co-routines.
+	 *
+	 * @param xHandle The handle of the calling co-routine.  This is the xHandle
+	 * parameter of the co-routine function.
+	 *
+	 * @param pxQueue The handle of the queue on which the data will be posted.
+	 * The handle is obtained as the return value when the queue is created using
+	 * the xQueueCreate() API function.
+	 *
+	 * @param pvItemToQueue A pointer to the data being posted onto the queue.
+	 * The number of bytes of each queued item is specified when the queue is
+	 * created.  This number of bytes is copied from pvItemToQueue into the queue
+	 * itself.
+	 *
+	 * @param xTickToDelay The number of ticks that the co-routine should block
+	 * to wait for space to become available on the queue, should space not be
+	 * available immediately. The actual amount of time this equates to is defined
+	 * by configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant
+	 * portTICK_RATE_MS can be used to convert ticks to milliseconds (see example
+	 * below).
+	 *
+	 * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+	 * data was successfully posted onto the queue, otherwise it will be set to an
+	 * error defined within ProjDefs.h.
+	 *
+	 * Example usage:
+	   <pre>
+	 // Co-routine function that blocks for a fixed period then posts a number onto
+	 // a queue.
+	 static void prvCoRoutineFlashTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+	 {
+	 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+	 static portBASE_TYPE xNumberToPost = 0;
+	 static portBASE_TYPE xResult;
+
+	    // Co-routines must begin with a call to crSTART().
+	    crSTART( xHandle );
+
+	    for( ;; )
+	    {
+	        // This assumes the queue has already been created.
+	        crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
+
+	        if( xResult != pdPASS )
+	        {
+	            // The message was not posted!
+	        }
+
+	        // Increment the number to be posted onto the queue.
+	        xNumberToPost++;
+
+	        // Delay for 100 ticks.
+	        crDELAY( xHandle, 100 );
+	    }
+
+	    // Co-routines must end with a call to crEND().
+	    crEND();
+	 }</pre>
+	 * \defgroup crQUEUE_SEND crQUEUE_SEND
+	 * \ingroup Tasks
+	 */
+#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult )			\
+{																						\
+	*pxResult = xQueueCRSend( pxQueue, pvItemToQueue, xTicksToWait );					\
+	if( *pxResult == errQUEUE_BLOCKED )													\
+	{																					\
+		crSET_STATE0( xHandle );														\
+		*pxResult = xQueueCRSend( pxQueue, pvItemToQueue, 0 );							\
+	}																					\
+	if( *pxResult == errQUEUE_YIELD )													\
+	{																					\
+		crSET_STATE1( xHandle );														\
+		*pxResult = pdPASS;																\
+	}																					\
+}
+
+	/**
+	 * croutine. h
+	 * <pre>
+	  crQUEUE_RECEIVE(
+	                     xCoRoutineHandle xHandle,
+	                     xQueueHandle pxQueue,
+	                     void *pvBuffer,
+	                     portTickType xTicksToWait,
+	                     portBASE_TYPE *pxResult
+	                 )</pre>
+	 *
+	 * The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
+	 * equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
+	 *
+	 * crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
+	 * xQueueSend() and xQueueReceive() can only be used from tasks.
+	 *
+	 * crQUEUE_RECEIVE can only be called from the co-routine function itself - not
+	 * from within a function called by the co-routine function.  This is because
+	 * co-routines do not maintain their own stack.
+	 *
+	 * See the co-routine section of the WEB documentation for information on
+	 * passing data between tasks and co-routines and between ISR's and
+	 * co-routines.
+	 *
+	 * @param xHandle The handle of the calling co-routine.  This is the xHandle
+	 * parameter of the co-routine function.
+	 *
+	 * @param pxQueue The handle of the queue from which the data will be received.
+	 * The handle is obtained as the return value when the queue is created using
+	 * the xQueueCreate() API function.
+	 *
+	 * @param pvBuffer The buffer into which the received item is to be copied.
+	 * The number of bytes of each queued item is specified when the queue is
+	 * created.  This number of bytes is copied into pvBuffer.
+	 *
+	 * @param xTickToDelay The number of ticks that the co-routine should block
+	 * to wait for data to become available from the queue, should data not be
+	 * available immediately. The actual amount of time this equates to is defined
+	 * by configTICK_RATE_HZ (set in FreeRTOSConfig.h).  The constant
+	 * portTICK_RATE_MS can be used to convert ticks to milliseconds (see the
+	 * crQUEUE_SEND example).
+	 *
+	 * @param pxResult The variable pointed to by pxResult will be set to pdPASS if
+	 * data was successfully retrieved from the queue, otherwise it will be set to
+	 * an error code as defined within ProjDefs.h.
+	 *
+	 * Example usage:
+	 <pre>
+	 // A co-routine receives the number of an LED to flash from a queue.  It
+	 // blocks on the queue until the number is received.
+	 static void prvCoRoutineFlashWorkTask( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+	 {
+	 // Variables in co-routines must be declared static if they must maintain value across a blocking call.
+	 static portBASE_TYPE xResult;
+	 static unsigned portBASE_TYPE uxLEDToFlash;
+
+	    // All co-routines must start with a call to crSTART().
+	    crSTART( xHandle );
+
+	    for( ;; )
+	    {
+	        // Wait for data to become available on the queue.
+	        crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+	        if( xResult == pdPASS )
+	        {
+	            // We received the LED to flash - flash it!
+	            vParTestToggleLED( uxLEDToFlash );
+	        }
+	    }
+
+	    crEND();
+	 }</pre>
+	 * \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
+	 * \ingroup Tasks
+	 */
+#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult )			\
+{																						\
+	*pxResult = xQueueCRReceive( pxQueue, pvBuffer, xTicksToWait );						\
+	if( *pxResult == errQUEUE_BLOCKED ) 												\
+	{																					\
+		crSET_STATE0( xHandle );														\
+		*pxResult = xQueueCRReceive( pxQueue, pvBuffer, 0 );							\
+	}																					\
+	if( *pxResult == errQUEUE_YIELD )													\
+	{																					\
+		crSET_STATE1( xHandle );														\
+		*pxResult = pdPASS;																\
+	}																					\
+}
+
+	/**
+	 * croutine. h
+	 * <pre>
+	  crQUEUE_SEND_FROM_ISR(
+	                            xQueueHandle pxQueue,
+	                            void *pvItemToQueue,
+	                            portBASE_TYPE xCoRoutinePreviouslyWoken
+	                       )</pre>
+	 *
+	 * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
+	 * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
+	 * functions used by tasks.
+	 *
+	 * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
+	 * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+	 * xQueueReceiveFromISR() can only be used to pass data between a task and and
+	 * ISR.
+	 *
+	 * crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
+	 * that is being used from within a co-routine.
+	 *
+	 * See the co-routine section of the WEB documentation for information on
+	 * passing data between tasks and co-routines and between ISR's and
+	 * co-routines.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
+	 * the same queue multiple times from a single interrupt.  The first call
+	 * should always pass in pdFALSE.  Subsequent calls should pass in
+	 * the value returned from the previous call.
+	 *
+	 * @return pdTRUE if a co-routine was woken by posting onto the queue.  This is
+	 * used by the ISR to determine if a context switch may be required following
+	 * the ISR.
+	 *
+	 * Example usage:
+	 <pre>
+	 // A co-routine that blocks on a queue waiting for characters to be received.
+	 static void vReceivingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+	 {
+	 char cRxedChar;
+	 portBASE_TYPE xResult;
+
+	     // All co-routines must start with a call to crSTART().
+	     crSTART( xHandle );
+
+	     for( ;; )
+	     {
+	         // Wait for data to become available on the queue.  This assumes the
+	         // queue xCommsRxQueue has already been created!
+	         crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
+
+	         // Was a character received?
+	         if( xResult == pdPASS )
+	         {
+	             // Process the character here.
+	         }
+	     }
+
+	     // All co-routines must end with a call to crEND().
+	     crEND();
+	 }
+
+	 // An ISR that uses a queue to send characters received on a serial port to
+	 // a co-routine.
+	 void vUART_ISR( void )
+	 {
+	 char cRxedChar;
+	 portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+	     // We loop around reading characters until there are none left in the UART.
+	     while( UART_RX_REG_NOT_EMPTY() )
+	     {
+	         // Obtain the character from the UART.
+	         cRxedChar = UART_RX_REG;
+
+	         // Post the character onto a queue.  xCRWokenByPost will be pdFALSE
+	         // the first time around the loop.  If the post causes a co-routine
+	         // to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
+	         // In this manner we can ensure that if more than one co-routine is
+	         // blocked on the queue only one is woken by this ISR no matter how
+	         // many characters are posted to the queue.
+	         xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
+	     }
+	 }</pre>
+	 * \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
+	 * \ingroup Tasks
+	 */
+#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken )
+
+
+	/**
+	 * croutine. h
+	 * <pre>
+	  crQUEUE_SEND_FROM_ISR(
+	                            xQueueHandle pxQueue,
+	                            void *pvBuffer,
+	                            portBASE_TYPE * pxCoRoutineWoken
+	                       )</pre>
+	 *
+	 * The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
+	 * co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
+	 * functions used by tasks.
+	 *
+	 * crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
+	 * pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
+	 * xQueueReceiveFromISR() can only be used to pass data between a task and and
+	 * ISR.
+	 *
+	 * crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
+	 * from a queue that is being used from within a co-routine (a co-routine
+	 * posted to the queue).
+	 *
+	 * See the co-routine section of the WEB documentation for information on
+	 * passing data between tasks and co-routines and between ISR's and
+	 * co-routines.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvBuffer A pointer to a buffer into which the received item will be
+	 * placed.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from the queue into
+	 * pvBuffer.
+	 *
+	 * @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
+	 * available on the queue.  If crQUEUE_RECEIVE_FROM_ISR causes such a
+	 * co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
+	 * *pxCoRoutineWoken will remain unchanged.
+	 *
+	 * @return pdTRUE an item was successfully received from the queue, otherwise
+	 * pdFALSE.
+	 *
+	 * Example usage:
+	 <pre>
+	 // A co-routine that posts a character to a queue then blocks for a fixed
+	 // period.  The character is incremented each time.
+	 static void vSendingCoRoutine( xCoRoutineHandle xHandle, unsigned portBASE_TYPE uxIndex )
+	 {
+	 // cChar holds its value while this co-routine is blocked and must therefore
+	 // be declared static.
+	 static char cCharToTx = 'a';
+	 portBASE_TYPE xResult;
+
+	     // All co-routines must start with a call to crSTART().
+	     crSTART( xHandle );
+
+	     for( ;; )
+	     {
+	         // Send the next character to the queue.
+	         crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
+
+	         if( xResult == pdPASS )
+	         {
+	             // The character was successfully posted to the queue.
+	         }
+			 else
+			 {
+				// Could not post the character to the queue.
+			 }
+
+	         // Enable the UART Tx interrupt to cause an interrupt in this
+			 // hypothetical UART.  The interrupt will obtain the character
+			 // from the queue and send it.
+			 ENABLE_RX_INTERRUPT();
+
+			 // Increment to the next character then block for a fixed period.
+			 // cCharToTx will maintain its value across the delay as it is
+			 // declared static.
+			 cCharToTx++;
+			 if( cCharToTx > 'x' )
+			 {
+				cCharToTx = 'a';
+			 }
+			 crDELAY( 100 );
+	     }
+
+	     // All co-routines must end with a call to crEND().
+	     crEND();
+	 }
+
+	 // An ISR that uses a queue to receive characters to send on a UART.
+	 void vUART_ISR( void )
+	 {
+	 char cCharToTx;
+	 portBASE_TYPE xCRWokenByPost = pdFALSE;
+
+	     while( UART_TX_REG_EMPTY() )
+	     {
+	         // Are there any characters in the queue waiting to be sent?
+			 // xCRWokenByPost will automatically be set to pdTRUE if a co-routine
+			 // is woken by the post - ensuring that only a single co-routine is
+			 // woken no matter how many times we go around this loop.
+	         if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
+			 {
+				 SEND_CHARACTER( cCharToTx );
+			 }
+	     }
+	 }</pre>
+	 * \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
+	 * \ingroup Tasks
+	 */
+#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( pxQueue, pvBuffer, pxCoRoutineWoken )
+
+	/*
+	 * This function is intended for internal use by the co-routine macros only.
+	 * The macro nature of the co-routine implementation requires that the
+	 * prototype appears here.  The function should not be used by application
+	 * writers.
+	 *
+	 * Removes the current co-routine from its ready list and places it in the
+	 * appropriate delayed list.
+	 */
+	void vCoRoutineAddToDelayedList(portTickType xTicksToDelay, xList *pxEventList);
+
+	/*
+	 * This function is intended for internal use by the queue implementation only.
+	 * The function should not be used by application writers.
+	 *
+	 * Removes the highest priority co-routine from the event list and places it in
+	 * the pending ready list.
+	 */
+	signed portBASE_TYPE xCoRoutineRemoveFromEventList(const xList *pxEventList);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CO_ROUTINE_H */
diff --git a/gyro_board/src/usb/FreeRTOS/include/list.h b/gyro_board/src/usb/FreeRTOS/include/list.h
new file mode 100644
index 0000000..5299ec9
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/list.h
@@ -0,0 +1,303 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*
+ * This is the list implementation used by the scheduler.  While it is tailored
+ * heavily for the schedulers needs, it is also available for use by
+ * application code.
+ *
+ * xLists can only store pointers to xListItems.  Each xListItem contains a
+ * numeric value (xItemValue).  Most of the time the lists are sorted in
+ * descending item value order.
+ *
+ * Lists are created already containing one list item.  The value of this
+ * item is the maximum possible that can be stored, it is therefore always at
+ * the end of the list and acts as a marker.  The list member pxHead always
+ * points to this marker - even though it is at the tail of the list.  This
+ * is because the tail contains a wrap back pointer to the true head of
+ * the list.
+ *
+ * In addition to it's value, each list item contains a pointer to the next
+ * item in the list (pxNext), a pointer to the list it is in (pxContainer)
+ * and a pointer to back to the object that contains it.  These later two
+ * pointers are included for efficiency of list manipulation.  There is
+ * effectively a two way link between the object containing the list item and
+ * the list item itself.
+ *
+ *
+ * \page ListIntroduction List Implementation
+ * \ingroup FreeRTOSIntro
+ */
+
+/*
+	Changes from V4.3.1
+
+	+ Included local const within listGET_OWNER_OF_NEXT_ENTRY() to assist
+	  compiler with optimisation.  Thanks B.R.
+*/
+
+#ifndef LIST_H
+#define LIST_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+	/*
+	 * Definition of the only type of object that a list can contain.
+	 */
+	struct xLIST_ITEM {
+		portTickType xItemValue;				/*< The value being listed.  In most cases this is used to sort the list in descending order. */
+		volatile struct xLIST_ITEM * pxNext;	/*< Pointer to the next xListItem in the list. */
+		volatile struct xLIST_ITEM * pxPrevious;/*< Pointer to the previous xListItem in the list. */
+		void * pvOwner;							/*< Pointer to the object (normally a TCB) that contains the list item.  There is therefore a two way link between the object containing the list item and the list item itself. */
+		void * pvContainer;						/*< Pointer to the list in which this list item is placed (if any). */
+	};
+	typedef struct xLIST_ITEM xListItem;		/* For some reason lint wants this as two separate definitions. */
+
+	struct xMINI_LIST_ITEM {
+		portTickType xItemValue;
+		volatile struct xLIST_ITEM *pxNext;
+		volatile struct xLIST_ITEM *pxPrevious;
+	};
+	typedef struct xMINI_LIST_ITEM xMiniListItem;
+
+	/*
+	 * Definition of the type of queue used by the scheduler.
+	 */
+	typedef struct xLIST {
+		volatile unsigned portBASE_TYPE uxNumberOfItems;
+		volatile xListItem * pxIndex;			/*< Used to walk through the list.  Points to the last item returned by a call to pvListGetOwnerOfNextEntry (). */
+		volatile xMiniListItem xListEnd;		/*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
+	} xList;
+
+	/*
+	 * Access macro to set the owner of a list item.  The owner of a list item
+	 * is the object (usually a TCB) that contains the list item.
+	 *
+	 * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
+	 * \ingroup LinkedList
+	 */
+#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner )		( pxListItem )->pvOwner = ( void * ) pxOwner
+
+	/*
+	 * Access macro to set the value of the list item.  In most cases the value is
+	 * used to sort the list in descending order.
+	 *
+	 * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
+	 * \ingroup LinkedList
+	 */
+#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )		( pxListItem )->xItemValue = xValue
+
+	/*
+	 * Access macro the retrieve the value of the list item.  The value can
+	 * represent anything - for example a the priority of a task, or the time at
+	 * which a task should be unblocked.
+	 *
+	 * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
+	 * \ingroup LinkedList
+	 */
+#define listGET_LIST_ITEM_VALUE( pxListItem )				( ( pxListItem )->xItemValue )
+
+	/*
+	 * Access macro to determine if a list contains any items.  The macro will
+	 * only have the value true if the list is empty.
+	 *
+	 * \page listLIST_IS_EMPTY listLIST_IS_EMPTY
+	 * \ingroup LinkedList
+	 */
+#define listLIST_IS_EMPTY( pxList )				( ( pxList )->uxNumberOfItems == ( unsigned portBASE_TYPE ) 0 )
+
+	/*
+	 * Access macro to return the number of items in the list.
+	 */
+#define listCURRENT_LIST_LENGTH( pxList )		( ( pxList )->uxNumberOfItems )
+
+	/*
+	 * Access function to obtain the owner of the next entry in a list.
+	 *
+	 * The list member pxIndex is used to walk through a list.  Calling
+	 * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
+	 * and returns that entries pxOwner parameter.  Using multiple calls to this
+	 * function it is therefore possible to move through every item contained in
+	 * a list.
+	 *
+	 * The pxOwner parameter of a list item is a pointer to the object that owns
+	 * the list item.  In the scheduler this is normally a task control block.
+	 * The pxOwner parameter effectively creates a two way link between the list
+	 * item and its owner.
+	 *
+	 * @param pxList The list from which the next item owner is to be returned.
+	 *
+	 * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
+	 * \ingroup LinkedList
+	 */
+#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )									\
+{																						\
+xList * const pxConstList = pxList;														\
+	/* Increment the index to the next item and return the item, ensuring */			\
+	/* we don't return the marker used at the end of the list.  */						\
+	( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;						\
+	if( ( pxConstList )->pxIndex == ( xListItem * ) &( ( pxConstList )->xListEnd ) )	\
+	{																					\
+		( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;					\
+	}																					\
+	pxTCB = ( pxConstList )->pxIndex->pvOwner;											\
+}
+
+
+	/*
+	 * Access function to obtain the owner of the first entry in a list.  Lists
+	 * are normally sorted in ascending item value order.
+	 *
+	 * This function returns the pxOwner member of the first item in the list.
+	 * The pxOwner parameter of a list item is a pointer to the object that owns
+	 * the list item.  In the scheduler this is normally a task control block.
+	 * The pxOwner parameter effectively creates a two way link between the list
+	 * item and its owner.
+	 *
+	 * @param pxList The list from which the owner of the head item is to be
+	 * returned.
+	 *
+	 * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
+	 * \ingroup LinkedList
+	 */
+#define listGET_OWNER_OF_HEAD_ENTRY( pxList )  ( ( pxList->uxNumberOfItems != ( unsigned portBASE_TYPE ) 0 ) ? ( (&( pxList->xListEnd ))->pxNext->pvOwner ) : ( NULL ) )
+
+	/*
+	 * Check to see if a list item is within a list.  The list item maintains a
+	 * "container" pointer that points to the list it is in.  All this macro does
+	 * is check to see if the container and the list match.
+	 *
+	 * @param pxList The list we want to know if the list item is within.
+	 * @param pxListItem The list item we want to know if is in the list.
+	 * @return pdTRUE is the list item is in the list, otherwise pdFALSE.
+	 * pointer against
+	 */
+#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( pxListItem )->pvContainer == ( void * ) pxList )
+
+	/*
+	 * Must be called before a list is used!  This initialises all the members
+	 * of the list structure and inserts the xListEnd item into the list as a
+	 * marker to the back of the list.
+	 *
+	 * @param pxList Pointer to the list being initialised.
+	 *
+	 * \page vListInitialise vListInitialise
+	 * \ingroup LinkedList
+	 */
+	void vListInitialise(xList *pxList);
+
+	/*
+	 * Must be called before a list item is used.  This sets the list container to
+	 * null so the item does not think that it is already contained in a list.
+	 *
+	 * @param pxItem Pointer to the list item being initialised.
+	 *
+	 * \page vListInitialiseItem vListInitialiseItem
+	 * \ingroup LinkedList
+	 */
+	void vListInitialiseItem(xListItem *pxItem);
+
+	/*
+	 * Insert a list item into a list.  The item will be inserted into the list in
+	 * a position determined by its item value (descending item value order).
+	 *
+	 * @param pxList The list into which the item is to be inserted.
+	 *
+	 * @param pxNewListItem The item to that is to be placed in the list.
+	 *
+	 * \page vListInsert vListInsert
+	 * \ingroup LinkedList
+	 */
+	void vListInsert(xList *pxList, xListItem *pxNewListItem);
+
+	/*
+	 * Insert a list item into a list.  The item will be inserted in a position
+	 * such that it will be the last item within the list returned by multiple
+	 * calls to listGET_OWNER_OF_NEXT_ENTRY.
+	 *
+	 * The list member pvIndex is used to walk through a list.  Calling
+	 * listGET_OWNER_OF_NEXT_ENTRY increments pvIndex to the next item in the list.
+	 * Placing an item in a list using vListInsertEnd effectively places the item
+	 * in the list position pointed to by pvIndex.  This means that every other
+	 * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
+	 * the pvIndex parameter again points to the item being inserted.
+	 *
+	 * @param pxList The list into which the item is to be inserted.
+	 *
+	 * @param pxNewListItem The list item to be inserted into the list.
+	 *
+	 * \page vListInsertEnd vListInsertEnd
+	 * \ingroup LinkedList
+	 */
+	void vListInsertEnd(xList *pxList, xListItem *pxNewListItem);
+
+	/*
+	 * Remove an item from a list.  The list item has a pointer to the list that
+	 * it is in, so only the list item need be passed into the function.
+	 *
+	 * @param vListRemove The item to be removed.  The item will remove itself from
+	 * the list pointed to by it's pxContainer parameter.
+	 *
+	 * \page vListRemove vListRemove
+	 * \ingroup LinkedList
+	 */
+	void vListRemove(xListItem *pxItemToRemove);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/mpu_wrappers.h b/gyro_board/src/usb/FreeRTOS/include/mpu_wrappers.h
new file mode 100644
index 0000000..ad8ce2d
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/mpu_wrappers.h
@@ -0,0 +1,135 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef MPU_WRAPPERS_H
+#define MPU_WRAPPERS_H
+
+/* This file redefines API functions to be called through a wrapper macro, but
+only for ports that are using the MPU. */
+#ifdef portUSING_MPU_WRAPPERS
+
+/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
+included from queue.c or task.c to prevent it from having an effect within
+those files. */
+#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#define xTaskGenericCreate				MPU_xTaskGenericCreate
+#define vTaskAllocateMPURegions			MPU_vTaskAllocateMPURegions
+#define vTaskDelete						MPU_vTaskDelete
+#define vTaskDelayUntil					MPU_vTaskDelayUntil
+#define vTaskDelay						MPU_vTaskDelay
+#define uxTaskPriorityGet				MPU_uxTaskPriorityGet
+#define vTaskPrioritySet				MPU_vTaskPrioritySet
+#define vTaskSuspend					MPU_vTaskSuspend
+#define xTaskIsTaskSuspended			MPU_xTaskIsTaskSuspended
+#define vTaskResume						MPU_vTaskResume
+#define vTaskSuspendAll					MPU_vTaskSuspendAll
+#define xTaskResumeAll					MPU_xTaskResumeAll
+#define xTaskGetTickCount				MPU_xTaskGetTickCount
+#define uxTaskGetNumberOfTasks			MPU_uxTaskGetNumberOfTasks
+#define vTaskList						MPU_vTaskList
+#define vTaskGetRunTimeStats			MPU_vTaskGetRunTimeStats
+#define vTaskStartTrace					MPU_vTaskStartTrace
+#define ulTaskEndTrace					MPU_ulTaskEndTrace
+#define vTaskSetApplicationTaskTag		MPU_vTaskSetApplicationTaskTag
+#define xTaskGetApplicationTaskTag		MPU_xTaskGetApplicationTaskTag
+#define xTaskCallApplicationTaskHook	MPU_xTaskCallApplicationTaskHook
+#define uxTaskGetStackHighWaterMark		MPU_uxTaskGetStackHighWaterMark
+#define xTaskGetCurrentTaskHandle		MPU_xTaskGetCurrentTaskHandle
+#define xTaskGetSchedulerState			MPU_xTaskGetSchedulerState
+
+#define xQueueCreate					MPU_xQueueCreate
+#define xQueueCreateMutex				MPU_xQueueCreateMutex
+#define xQueueGiveMutexRecursive		MPU_xQueueGiveMutexRecursive
+#define xQueueTakeMutexRecursive		MPU_xQueueTakeMutexRecursive
+#define xQueueCreateCountingSemaphore	MPU_xQueueCreateCountingSemaphore
+#define xQueueGenericSend				MPU_xQueueGenericSend
+#define xQueueAltGenericSend			MPU_xQueueAltGenericSend
+#define xQueueAltGenericReceive			MPU_xQueueAltGenericReceive
+#define xQueueGenericReceive			MPU_xQueueGenericReceive
+#define uxQueueMessagesWaiting			MPU_uxQueueMessagesWaiting
+#define vQueueDelete					MPU_vQueueDelete
+
+#define pvPortMalloc					MPU_pvPortMalloc
+#define vPortFree						MPU_vPortFree
+#define xPortGetFreeHeapSize			MPU_xPortGetFreeHeapSize
+#define vPortInitialiseBlocks			MPU_vPortInitialiseBlocks
+
+#if configQUEUE_REGISTRY_SIZE > 0
+#define vQueueAddToRegistry				MPU_vQueueAddToRegistry
+#define vQueueUnregisterQueue			MPU_vQueueUnregisterQueue
+#endif
+
+/* Remove the privileged function macro. */
+#define PRIVILEGED_FUNCTION
+
+#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+/* Ensure API functions go in the privileged execution section. */
+#define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions")))
+#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
+//#define PRIVILEGED_DATA
+
+#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
+
+#else /* portUSING_MPU_WRAPPERS */
+
+#define PRIVILEGED_FUNCTION
+#define PRIVILEGED_DATA
+#define portUSING_MPU_WRAPPERS 0
+
+#endif /* portUSING_MPU_WRAPPERS */
+
+
+#endif /* MPU_WRAPPERS_H */
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/portable.h b/gyro_board/src/usb/FreeRTOS/include/portable.h
new file mode 100644
index 0000000..385be74
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/portable.h
@@ -0,0 +1,391 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*-----------------------------------------------------------
+ * Portable layer API.  Each function must be defined for each port.
+ *----------------------------------------------------------*/
+
+#ifndef PORTABLE_H
+#define PORTABLE_H
+
+/* Include the macro file relevant to the port being used. */
+
+#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
+#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
+typedef void (__interrupt __far *pxISR)();
+#endif
+
+#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
+#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
+typedef void (__interrupt __far *pxISR)();
+#endif
+
+#ifdef GCC_MEGA_AVR
+#include "../portable/GCC/ATMega323/portmacro.h"
+#endif
+
+#ifdef IAR_MEGA_AVR
+#include "../portable/IAR/ATMega323/portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC24_PORT
+#include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h"
+#endif
+
+#ifdef MPLAB_DSPIC_PORT
+#include "..\..\Source\portable\MPLAB\PIC24_dsPIC\portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC18F_PORT
+#include "..\..\Source\portable\MPLAB\PIC18F\portmacro.h"
+#endif
+
+#ifdef MPLAB_PIC32MX_PORT
+#include "..\..\Source\portable\MPLAB\PIC32MX\portmacro.h"
+#endif
+
+#ifdef _FEDPICC
+#include "libFreeRTOS/Include/portmacro.h"
+#endif
+
+#ifdef SDCC_CYGNAL
+#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7
+#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
+#endif
+
+#ifdef GCC_ARM7_ECLIPSE
+#include "portmacro.h"
+#endif
+
+#ifdef ROWLEY_LPC23xx
+#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
+#endif
+
+#ifdef IAR_MSP430
+#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
+#endif
+
+#ifdef GCC_MSP430
+#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ROWLEY_MSP430
+#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
+#endif
+
+#ifdef ARM7_LPC21xx_KEIL_RVDS
+#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
+#endif
+
+#ifdef SAM7_GCC
+#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
+#endif
+
+#ifdef SAM7_IAR
+#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
+#endif
+
+#ifdef SAM9XE_IAR
+#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
+#endif
+
+#ifdef LPC2000_IAR
+#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
+#endif
+
+#ifdef STR71X_IAR
+#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
+#endif
+
+#ifdef STR75X_IAR
+#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
+#endif
+
+#ifdef STR75X_GCC
+#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
+#endif
+
+#ifdef STR91X_IAR
+#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
+#endif
+
+#ifdef GCC_H8S
+#include "../../Source/portable/GCC/H8S2329/portmacro.h"
+#endif
+
+#ifdef GCC_AT91FR40008
+#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
+#endif
+
+#ifdef RVDS_ARMCM3_LM3S102
+#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3_LM3S102
+#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef GCC_ARMCM3
+#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARM_CM3
+#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef IAR_ARMCM3_LM
+#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
+#endif
+
+#ifdef HCS12_CODE_WARRIOR
+#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
+#endif
+
+#ifdef MICROBLAZE_GCC
+#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
+#endif
+
+#ifdef TERN_EE
+#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
+#endif
+
+#ifdef GCC_HCS12
+#include "../../Source/portable/GCC/HCS12/portmacro.h"
+#endif
+
+#ifdef GCC_MCF5235
+#include "../../Source/portable/GCC/MCF5235/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_GCC
+#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef COLDFIRE_V2_CODEWARRIOR
+#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
+#endif
+
+#ifdef GCC_PPC405
+#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
+#endif
+
+#ifdef GCC_PPC440
+#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
+#endif
+
+#ifdef _16FX_SOFTUNE
+#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
+#endif
+
+#ifdef BCC_INDUSTRIAL_PC_PORT
+/* A short file name has to be used in place of the normal
+FreeRTOSConfig.h when using the Borland compiler. */
+#include "frconfig.h"
+#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
+typedef void (__interrupt __far *pxISR)();
+#endif
+
+#ifdef BCC_FLASH_LITE_186_PORT
+/* A short file name has to be used in place of the normal
+FreeRTOSConfig.h when using the Borland compiler. */
+#include "frconfig.h"
+#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
+typedef void (__interrupt __far *pxISR)();
+#endif
+
+#ifdef __GNUC__
+#ifdef __AVR32_AVR32A__
+#include "portmacro.h"
+#endif
+#endif
+
+#ifdef __ICCAVR32__
+#ifdef __CORE__
+#if __CORE__ == __AVR32A__
+#include "portmacro.h"
+#endif
+#endif
+#endif
+
+#ifdef __91467D
+#include "portmacro.h"
+#endif
+
+#ifdef __96340
+#include "portmacro.h"
+#endif
+
+
+#ifdef __IAR_V850ES_Fx3__
+#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3__
+#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx3_L__
+#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Jx2__
+#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_V850ES_Hx2__
+#include "../../Source/portable/IAR/V850ES/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3__
+#include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+#ifdef __IAR_78K0R_Kx3L__
+#include "../../Source/portable/IAR/78K0R/portmacro.h"
+#endif
+
+/* Catch all to ensure portmacro.h is included in the build.  Newer demos
+have the path as part of the project options, rather than as relative from
+the project location.  If portENTER_CRITICAL() has not been defined then
+portmacro.h has not yet been included - as every portmacro.h provides a
+portENTER_CRITICAL() definition.  Check the demo application for your demo
+to find the path to the correct portmacro.h file. */
+#ifndef portENTER_CRITICAL
+#include "portmacro.h"
+#endif
+
+#if portBYTE_ALIGNMENT == 8
+#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
+#endif
+
+#if portBYTE_ALIGNMENT == 4
+#define portBYTE_ALIGNMENT_MASK	( 0x0003 )
+#endif
+
+#if portBYTE_ALIGNMENT == 2
+#define portBYTE_ALIGNMENT_MASK	( 0x0001 )
+#endif
+
+#if portBYTE_ALIGNMENT == 1
+#define portBYTE_ALIGNMENT_MASK	( 0x0000 )
+#endif
+
+#ifndef portBYTE_ALIGNMENT_MASK
+#error "Invalid portBYTE_ALIGNMENT definition"
+#endif
+
+#ifndef portNUM_CONFIGURABLE_REGIONS
+#define portNUM_CONFIGURABLE_REGIONS 1
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "mpu_wrappers.h"
+
+	/*
+	 * Setup the stack of a new task so it is ready to be placed under the
+	 * scheduler control.  The registers have to be placed on the stack in
+	 * the order that the port expects to find them.
+	 *
+	 */
+#if( portUSING_MPU_WRAPPERS == 1 )
+	portSTACK_TYPE *pxPortInitialiseStack(portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters, portBASE_TYPE xRunPrivileged) PRIVILEGED_FUNCTION;
+#else
+	portSTACK_TYPE *pxPortInitialiseStack(portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters);
+#endif
+
+	/*
+	 * Map to the memory management routines required for the port.
+	 */
+	void *pvPortMalloc(size_t xSize) PRIVILEGED_FUNCTION;
+	void vPortFree(void *pv) PRIVILEGED_FUNCTION;
+	void vPortInitialiseBlocks(void) PRIVILEGED_FUNCTION;
+	size_t xPortGetFreeHeapSize(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Setup the hardware ready for the scheduler to take control.  This generally
+	 * sets up a tick interrupt and sets timers for the correct tick frequency.
+	 */
+	portBASE_TYPE xPortStartScheduler(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
+	 * the hardware is left in its original condition after the scheduler stops
+	 * executing.
+	 */
+	void vPortEndScheduler(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * The structures and methods of manipulating the MPU are contained within the
+	 * port layer.
+	 *
+	 * Fills the xMPUSettings structure with the memory region information
+	 * contained in xRegions.
+	 */
+#if( portUSING_MPU_WRAPPERS == 1 )
+	struct xMEMORY_REGION;
+	void vPortStoreTaskMPUSettings(xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, portSTACK_TYPE *pxBottomOfStack, unsigned short usStackDepth) PRIVILEGED_FUNCTION;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTABLE_H */
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/projdefs.h b/gyro_board/src/usb/FreeRTOS/include/projdefs.h
new file mode 100644
index 0000000..543992d
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/projdefs.h
@@ -0,0 +1,77 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef PROJDEFS_H
+#define PROJDEFS_H
+
+/* Defines the prototype to which task functions must conform. */
+typedef void (*pdTASK_CODE)(void *);
+
+#define pdTRUE		( 1 )
+#define pdFALSE		( 0 )
+
+#define pdPASS									( 1 )
+#define pdFAIL									( 0 )
+#define errQUEUE_EMPTY							( 0 )
+#define errQUEUE_FULL							( 0 )
+
+/* Error definitions. */
+#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY	( -1 )
+#define errNO_TASK_TO_RUN						( -2 )
+#define errQUEUE_BLOCKED						( -4 )
+#define errQUEUE_YIELD							( -5 )
+
+#endif /* PROJDEFS_H */
+
+
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/queue.h b/gyro_board/src/usb/FreeRTOS/include/queue.h
new file mode 100644
index 0000000..8d5dcba
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/queue.h
@@ -0,0 +1,1262 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef INC_FREERTOS_H
+#error "#include FreeRTOS.h" must appear in source files before "#include queue.h"
+#endif
+
+
+
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "mpu_wrappers.h"
+
+
+	typedef void * xQueueHandle;
+
+
+	/* For internal use only. */
+#define	queueSEND_TO_BACK	( 0 )
+#define	queueSEND_TO_FRONT	( 1 )
+
+
+	/**
+	 * queue. h
+	 * <pre>
+	 xQueueHandle xQueueCreate(
+								  unsigned portBASE_TYPE uxQueueLength,
+								  unsigned portBASE_TYPE uxItemSize
+							  );
+	 * </pre>
+	 *
+	 * Creates a new queue instance.  This allocates the storage required by the
+	 * new queue and returns a handle for the queue.
+	 *
+	 * @param uxQueueLength The maximum number of items that the queue can contain.
+	 *
+	 * @param uxItemSize The number of bytes each item in the queue will require.
+	 * Items are queued by copy, not by reference, so this is the number of bytes
+	 * that will be copied for each posted item.  Each item on the queue must be
+	 * the same size.
+	 *
+	 * @return If the queue is successfully create then a handle to the newly
+	 * created queue is returned.  If the queue cannot be created then 0 is
+	 * returned.
+	 *
+	 * Example usage:
+	   <pre>
+	 struct AMessage
+	 {
+		char ucMessageID;
+		char ucData[ 20 ];
+	 };
+
+	 void vATask( void *pvParameters )
+	 {
+	 xQueueHandle xQueue1, xQueue2;
+
+		// Create a queue capable of containing 10 unsigned long values.
+		xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+		if( xQueue1 == 0 )
+		{
+			// Queue was not created and must not be used.
+		}
+
+		// Create a queue capable of containing 10 pointers to AMessage structures.
+		// These should be passed by pointer as they contain a lot of data.
+		xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+		if( xQueue2 == 0 )
+		{
+			// Queue was not created and must not be used.
+		}
+
+		// ... Rest of task code.
+	 }
+	 </pre>
+	 * \defgroup xQueueCreate xQueueCreate
+	 * \ingroup QueueManagement
+	 */
+	xQueueHandle xQueueCreate(unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize);
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueSendToToFront(
+									   xQueueHandle	xQueue,
+									   const	void	*	pvItemToQueue,
+									   portTickType	xTicksToWait
+								   );
+	 * </pre>
+	 *
+	 * This is a macro that calls xQueueGenericSend().
+	 *
+	 * Post an item to the front of a queue.  The item is queued by copy, not by
+	 * reference.  This function must not be called from an interrupt service
+	 * routine.  See xQueueSendFromISR () for an alternative which may be used
+	 * in an ISR.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param xTicksToWait The maximum amount of time the task should block
+	 * waiting for space to become available on the queue, should it already
+	 * be full.  The call will return immediately if this is set to 0 and the
+	 * queue is full.  The time is defined in tick periods so the constant
+	 * portTICK_RATE_MS should be used to convert to real time if this is required.
+	 *
+	 * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+	 *
+	 * Example usage:
+	   <pre>
+	 struct AMessage
+	 {
+		char ucMessageID;
+		char ucData[ 20 ];
+	 } xMessage;
+
+	 unsigned long ulVar = 10UL;
+
+	 void vATask( void *pvParameters )
+	 {
+	 xQueueHandle xQueue1, xQueue2;
+	 struct AMessage *pxMessage;
+
+		// Create a queue capable of containing 10 unsigned long values.
+		xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+		// Create a queue capable of containing 10 pointers to AMessage structures.
+		// These should be passed by pointer as they contain a lot of data.
+		xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+		// ...
+
+		if( xQueue1 != 0 )
+		{
+			// Send an unsigned long.  Wait for 10 ticks for space to become
+			// available if necessary.
+			if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+			{
+				// Failed to post the message, even after 10 ticks.
+			}
+		}
+
+		if( xQueue2 != 0 )
+		{
+			// Send a pointer to a struct AMessage object.  Don't block if the
+			// queue is already full.
+			pxMessage = & xMessage;
+			xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+		}
+
+		// ... Rest of task code.
+	 }
+	 </pre>
+	 * \defgroup xQueueSend xQueueSend
+	 * \ingroup QueueManagement
+	 */
+#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT )
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueSendToBack(
+									   xQueueHandle	xQueue,
+									   const	void	*	pvItemToQueue,
+									   portTickType	xTicksToWait
+								   );
+	 * </pre>
+	 *
+	 * This is a macro that calls xQueueGenericSend().
+	 *
+	 * Post an item to the back of a queue.  The item is queued by copy, not by
+	 * reference.  This function must not be called from an interrupt service
+	 * routine.  See xQueueSendFromISR () for an alternative which may be used
+	 * in an ISR.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param xTicksToWait The maximum amount of time the task should block
+	 * waiting for space to become available on the queue, should it already
+	 * be full.  The call will return immediately if this is set to 0 and the queue
+	 * is full.  The  time is defined in tick periods so the constant
+	 * portTICK_RATE_MS should be used to convert to real time if this is required.
+	 *
+	 * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+	 *
+	 * Example usage:
+	   <pre>
+	 struct AMessage
+	 {
+		char ucMessageID;
+		char ucData[ 20 ];
+	 } xMessage;
+
+	 unsigned long ulVar = 10UL;
+
+	 void vATask( void *pvParameters )
+	 {
+	 xQueueHandle xQueue1, xQueue2;
+	 struct AMessage *pxMessage;
+
+		// Create a queue capable of containing 10 unsigned long values.
+		xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+		// Create a queue capable of containing 10 pointers to AMessage structures.
+		// These should be passed by pointer as they contain a lot of data.
+		xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+		// ...
+
+		if( xQueue1 != 0 )
+		{
+			// Send an unsigned long.  Wait for 10 ticks for space to become
+			// available if necessary.
+			if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+			{
+				// Failed to post the message, even after 10 ticks.
+			}
+		}
+
+		if( xQueue2 != 0 )
+		{
+			// Send a pointer to a struct AMessage object.  Don't block if the
+			// queue is already full.
+			pxMessage = & xMessage;
+			xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+		}
+
+		// ... Rest of task code.
+	 }
+	 </pre>
+	 * \defgroup xQueueSend xQueueSend
+	 * \ingroup QueueManagement
+	 */
+#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueSend(
+								  xQueueHandle xQueue,
+								  const void * pvItemToQueue,
+								  portTickType xTicksToWait
+							 );
+	 * </pre>
+	 *
+	 * This is a macro that calls xQueueGenericSend().  It is included for
+	 * backward compatibility with versions of FreeRTOS.org that did not
+	 * include the xQueueSendToFront() and xQueueSendToBack() macros.  It is
+	 * equivalent to xQueueSendToBack().
+	 *
+	 * Post an item on a queue.  The item is queued by copy, not by reference.
+	 * This function must not be called from an interrupt service routine.
+	 * See xQueueSendFromISR () for an alternative which may be used in an ISR.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param xTicksToWait The maximum amount of time the task should block
+	 * waiting for space to become available on the queue, should it already
+	 * be full.  The call will return immediately if this is set to 0 and the
+	 * queue is full.  The time is defined in tick periods so the constant
+	 * portTICK_RATE_MS should be used to convert to real time if this is required.
+	 *
+	 * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+	 *
+	 * Example usage:
+	   <pre>
+	 struct AMessage
+	 {
+		char ucMessageID;
+		char ucData[ 20 ];
+	 } xMessage;
+
+	 unsigned long ulVar = 10UL;
+
+	 void vATask( void *pvParameters )
+	 {
+	 xQueueHandle xQueue1, xQueue2;
+	 struct AMessage *pxMessage;
+
+		// Create a queue capable of containing 10 unsigned long values.
+		xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+		// Create a queue capable of containing 10 pointers to AMessage structures.
+		// These should be passed by pointer as they contain a lot of data.
+		xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+		// ...
+
+		if( xQueue1 != 0 )
+		{
+			// Send an unsigned long.  Wait for 10 ticks for space to become
+			// available if necessary.
+			if( xQueueSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10 ) != pdPASS )
+			{
+				// Failed to post the message, even after 10 ticks.
+			}
+		}
+
+		if( xQueue2 != 0 )
+		{
+			// Send a pointer to a struct AMessage object.  Don't block if the
+			// queue is already full.
+			pxMessage = & xMessage;
+			xQueueSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0 );
+		}
+
+		// ... Rest of task code.
+	 }
+	 </pre>
+	 * \defgroup xQueueSend xQueueSend
+	 * \ingroup QueueManagement
+	 */
+#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )
+
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueGenericSend(
+										xQueueHandle xQueue,
+										const void * pvItemToQueue,
+										portTickType xTicksToWait
+										portBASE_TYPE xCopyPosition
+									);
+	 * </pre>
+	 *
+	 * It is preferred that the macros xQueueSend(), xQueueSendToFront() and
+	 * xQueueSendToBack() are used in place of calling this function directly.
+	 *
+	 * Post an item on a queue.  The item is queued by copy, not by reference.
+	 * This function must not be called from an interrupt service routine.
+	 * See xQueueSendFromISR () for an alternative which may be used in an ISR.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param xTicksToWait The maximum amount of time the task should block
+	 * waiting for space to become available on the queue, should it already
+	 * be full.  The call will return immediately if this is set to 0 and the
+	 * queue is full.  The time is defined in tick periods so the constant
+	 * portTICK_RATE_MS should be used to convert to real time if this is required.
+	 *
+	 * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the
+	 * item at the back of the queue, or queueSEND_TO_FRONT to place the item
+	 * at the front of the queue (for high priority messages).
+	 *
+	 * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
+	 *
+	 * Example usage:
+	   <pre>
+	 struct AMessage
+	 {
+		char ucMessageID;
+		char ucData[ 20 ];
+	 } xMessage;
+
+	 unsigned long ulVar = 10UL;
+
+	 void vATask( void *pvParameters )
+	 {
+	 xQueueHandle xQueue1, xQueue2;
+	 struct AMessage *pxMessage;
+
+		// Create a queue capable of containing 10 unsigned long values.
+		xQueue1 = xQueueCreate( 10, sizeof( unsigned long ) );
+
+		// Create a queue capable of containing 10 pointers to AMessage structures.
+		// These should be passed by pointer as they contain a lot of data.
+		xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+		// ...
+
+		if( xQueue1 != 0 )
+		{
+			// Send an unsigned long.  Wait for 10 ticks for space to become
+			// available if necessary.
+			if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( portTickType ) 10, queueSEND_TO_BACK ) != pdPASS )
+			{
+				// Failed to post the message, even after 10 ticks.
+			}
+		}
+
+		if( xQueue2 != 0 )
+		{
+			// Send a pointer to a struct AMessage object.  Don't block if the
+			// queue is already full.
+			pxMessage = & xMessage;
+			xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( portTickType ) 0, queueSEND_TO_BACK );
+		}
+
+		// ... Rest of task code.
+	 }
+	 </pre>
+	 * \defgroup xQueueSend xQueueSend
+	 * \ingroup QueueManagement
+	 */
+	signed portBASE_TYPE xQueueGenericSend(xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition);
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueuePeek(
+								 xQueueHandle xQueue,
+								 void *pvBuffer,
+								 portTickType xTicksToWait
+							 );</pre>
+	 *
+	 * This is a macro that calls the xQueueGenericReceive() function.
+	 *
+	 * Receive an item from a queue without removing the item from the queue.
+	 * The item is received by copy so a buffer of adequate size must be
+	 * provided.  The number of bytes copied into the buffer was defined when
+	 * the queue was created.
+	 *
+	 * Successfully received items remain on the queue so will be returned again
+	 * by the next call, or a call to xQueueReceive().
+	 *
+	 * This macro must not be used in an interrupt service routine.
+	 *
+	 * @param pxQueue The handle to the queue from which the item is to be
+	 * received.
+	 *
+	 * @param pvBuffer Pointer to the buffer into which the received item will
+	 * be copied.
+	 *
+	 * @param xTicksToWait The maximum amount of time the task should block
+	 * waiting for an item to receive should the queue be empty at the time
+	 * of the call.	 The time is defined in tick periods so the constant
+	 * portTICK_RATE_MS should be used to convert to real time if this is required.
+	 * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue
+	 * is empty.
+	 *
+	 * @return pdTRUE if an item was successfully received from the queue,
+	 * otherwise pdFALSE.
+	 *
+	 * Example usage:
+	   <pre>
+	 struct AMessage
+	 {
+		char ucMessageID;
+		char ucData[ 20 ];
+	 } xMessage;
+
+	 xQueueHandle xQueue;
+
+	 // Task to create a queue and post a value.
+	 void vATask( void *pvParameters )
+	 {
+	 struct AMessage *pxMessage;
+
+		// Create a queue capable of containing 10 pointers to AMessage structures.
+		// These should be passed by pointer as they contain a lot of data.
+		xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+		if( xQueue == 0 )
+		{
+			// Failed to create the queue.
+		}
+
+		// ...
+
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+		// ... Rest of task code.
+	 }
+
+	 // Task to peek the data from the queue.
+	 void vADifferentTask( void *pvParameters )
+	 {
+	 struct AMessage *pxRxedMessage;
+
+		if( xQueue != 0 )
+		{
+			// Peek a message on the created queue.  Block for 10 ticks if a
+			// message is not immediately available.
+			if( xQueuePeek( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+			{
+				// pcRxedMessage now points to the struct AMessage variable posted
+				// by vATask, but the item still remains on the queue.
+			}
+		}
+
+		// ... Rest of task code.
+	 }
+	 </pre>
+	 * \defgroup xQueueReceive xQueueReceive
+	 * \ingroup QueueManagement
+	 */
+#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( xQueue, pvBuffer, xTicksToWait, pdTRUE )
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueReceive(
+									 xQueueHandle xQueue,
+									 void *pvBuffer,
+									 portTickType xTicksToWait
+								);</pre>
+	 *
+	 * This is a macro that calls the xQueueGenericReceive() function.
+	 *
+	 * Receive an item from a queue.  The item is received by copy so a buffer of
+	 * adequate size must be provided.  The number of bytes copied into the buffer
+	 * was defined when the queue was created.
+	 *
+	 * Successfully received items are removed from the queue.
+	 *
+	 * This function must not be used in an interrupt service routine.  See
+	 * xQueueReceiveFromISR for an alternative that can.
+	 *
+	 * @param pxQueue The handle to the queue from which the item is to be
+	 * received.
+	 *
+	 * @param pvBuffer Pointer to the buffer into which the received item will
+	 * be copied.
+	 *
+	 * @param xTicksToWait The maximum amount of time the task should block
+	 * waiting for an item to receive should the queue be empty at the time
+	 * of the call.	 xQueueReceive() will return immediately if xTicksToWait
+	 * is zero and the queue is empty.  The time is defined in tick periods so the
+	 * constant portTICK_RATE_MS should be used to convert to real time if this is
+	 * required.
+	 *
+	 * @return pdTRUE if an item was successfully received from the queue,
+	 * otherwise pdFALSE.
+	 *
+	 * Example usage:
+	   <pre>
+	 struct AMessage
+	 {
+		char ucMessageID;
+		char ucData[ 20 ];
+	 } xMessage;
+
+	 xQueueHandle xQueue;
+
+	 // Task to create a queue and post a value.
+	 void vATask( void *pvParameters )
+	 {
+	 struct AMessage *pxMessage;
+
+		// Create a queue capable of containing 10 pointers to AMessage structures.
+		// These should be passed by pointer as they contain a lot of data.
+		xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+		if( xQueue == 0 )
+		{
+			// Failed to create the queue.
+		}
+
+		// ...
+
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+		// ... Rest of task code.
+	 }
+
+	 // Task to receive from the queue.
+	 void vADifferentTask( void *pvParameters )
+	 {
+	 struct AMessage *pxRxedMessage;
+
+		if( xQueue != 0 )
+		{
+			// Receive a message on the created queue.  Block for 10 ticks if a
+			// message is not immediately available.
+			if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+			{
+				// pcRxedMessage now points to the struct AMessage variable posted
+				// by vATask.
+			}
+		}
+
+		// ... Rest of task code.
+	 }
+	 </pre>
+	 * \defgroup xQueueReceive xQueueReceive
+	 * \ingroup QueueManagement
+	 */
+#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( xQueue, pvBuffer, xTicksToWait, pdFALSE )
+
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueGenericReceive(
+										   xQueueHandle	xQueue,
+										   void	*pvBuffer,
+										   portTickType	xTicksToWait
+										   portBASE_TYPE	xJustPeek
+										);</pre>
+	 *
+	 * It is preferred that the macro xQueueReceive() be used rather than calling
+	 * this function directly.
+	 *
+	 * Receive an item from a queue.  The item is received by copy so a buffer of
+	 * adequate size must be provided.  The number of bytes copied into the buffer
+	 * was defined when the queue was created.
+	 *
+	 * This function must not be used in an interrupt service routine.  See
+	 * xQueueReceiveFromISR for an alternative that can.
+	 *
+	 * @param pxQueue The handle to the queue from which the item is to be
+	 * received.
+	 *
+	 * @param pvBuffer Pointer to the buffer into which the received item will
+	 * be copied.
+	 *
+	 * @param xTicksToWait The maximum amount of time the task should block
+	 * waiting for an item to receive should the queue be empty at the time
+	 * of the call.	 The time is defined in tick periods so the constant
+	 * portTICK_RATE_MS should be used to convert to real time if this is required.
+	 * xQueueGenericReceive() will return immediately if the queue is empty and
+	 * xTicksToWait is 0.
+	 *
+	 * @param xJustPeek When set to true, the item received from the queue is not
+	 * actually removed from the queue - meaning a subsequent call to
+	 * xQueueReceive() will return the same item.  When set to false, the item
+	 * being received from the queue is also removed from the queue.
+	 *
+	 * @return pdTRUE if an item was successfully received from the queue,
+	 * otherwise pdFALSE.
+	 *
+	 * Example usage:
+	   <pre>
+	 struct AMessage
+	 {
+		char ucMessageID;
+		char ucData[ 20 ];
+	 } xMessage;
+
+	 xQueueHandle xQueue;
+
+	 // Task to create a queue and post a value.
+	 void vATask( void *pvParameters )
+	 {
+	 struct AMessage *pxMessage;
+
+		// Create a queue capable of containing 10 pointers to AMessage structures.
+		// These should be passed by pointer as they contain a lot of data.
+		xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+		if( xQueue == 0 )
+		{
+			// Failed to create the queue.
+		}
+
+		// ...
+
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );
+
+		// ... Rest of task code.
+	 }
+
+	 // Task to receive from the queue.
+	 void vADifferentTask( void *pvParameters )
+	 {
+	 struct AMessage *pxRxedMessage;
+
+		if( xQueue != 0 )
+		{
+			// Receive a message on the created queue.  Block for 10 ticks if a
+			// message is not immediately available.
+			if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
+			{
+				// pcRxedMessage now points to the struct AMessage variable posted
+				// by vATask.
+			}
+		}
+
+		// ... Rest of task code.
+	 }
+	 </pre>
+	 * \defgroup xQueueReceive xQueueReceive
+	 * \ingroup QueueManagement
+	 */
+	signed portBASE_TYPE xQueueGenericReceive(xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeek);
+
+	/**
+	 * queue. h
+	 * <pre>unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue );</pre>
+	 *
+	 * Return the number of messages stored in a queue.
+	 *
+	 * @param xQueue A handle to the queue being queried.
+	 *
+	 * @return The number of messages available in the queue.
+	 *
+	 * \page uxQueueMessagesWaiting uxQueueMessagesWaiting
+	 * \ingroup QueueManagement
+	 */
+	unsigned portBASE_TYPE uxQueueMessagesWaiting(const xQueueHandle xQueue);
+
+	/**
+	 * queue. h
+	 * <pre>void vQueueDelete( xQueueHandle xQueue );</pre>
+	 *
+	 * Delete a queue - freeing all the memory allocated for storing of items
+	 * placed on the queue.
+	 *
+	 * @param xQueue A handle to the queue to be deleted.
+	 *
+	 * \page vQueueDelete vQueueDelete
+	 * \ingroup QueueManagement
+	 */
+	void vQueueDelete(xQueueHandle xQueue);
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueSendToFrontFromISR(
+											 xQueueHandle pxQueue,
+											 const void *pvItemToQueue,
+											 portBASE_TYPE *pxHigherPriorityTaskWoken
+										  );
+	 </pre>
+	 *
+	 * This is a macro that calls xQueueGenericSendFromISR().
+	 *
+	 * Post an item to the front of a queue.  It is safe to use this macro from
+	 * within an interrupt service routine.
+	 *
+	 * Items are queued by copy not reference so it is preferable to only
+	 * queue small items, especially when called from an ISR.  In most cases
+	 * it would be preferable to store a pointer to the item being queued.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set
+	 * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+	 * to unblock, and the unblocked task has a priority higher than the currently
+	 * running task.  If xQueueSendToFromFromISR() sets this value to pdTRUE then
+	 * a context switch should be requested before the interrupt is exited.
+	 *
+	 * @return pdTRUE if the data was successfully sent to the queue, otherwise
+	 * errQUEUE_FULL.
+	 *
+	 * Example usage for buffered IO (where the ISR can obtain more than one value
+	 * per call):
+	   <pre>
+	 void vBufferISR( void )
+	 {
+	 char cIn;
+	 portBASE_TYPE xHigherPrioritTaskWoken;
+
+		// We have not woken a task at the start of the ISR.
+		xHigherPriorityTaskWoken = pdFALSE;
+
+		// Loop until the buffer is empty.
+		do
+		{
+			// Obtain a byte from the buffer.
+			cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+			// Post the byte.
+			xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+		} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+		// Now the buffer is empty we can switch context if necessary.
+		if( xHigherPriorityTaskWoken )
+		{
+			taskYIELD ();
+		}
+	 }
+	 </pre>
+	 *
+	 * \defgroup xQueueSendFromISR xQueueSendFromISR
+	 * \ingroup QueueManagement
+	 */
+#define xQueueSendToFrontFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_FRONT )
+
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueSendToBackFromISR(
+											 xQueueHandle pxQueue,
+											 const void *pvItemToQueue,
+											 portBASE_TYPE *pxHigherPriorityTaskWoken
+										  );
+	 </pre>
+	 *
+	 * This is a macro that calls xQueueGenericSendFromISR().
+	 *
+	 * Post an item to the back of a queue.  It is safe to use this macro from
+	 * within an interrupt service routine.
+	 *
+	 * Items are queued by copy not reference so it is preferable to only
+	 * queue small items, especially when called from an ISR.  In most cases
+	 * it would be preferable to store a pointer to the item being queued.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set
+	 * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+	 * to unblock, and the unblocked task has a priority higher than the currently
+	 * running task.  If xQueueSendToBackFromISR() sets this value to pdTRUE then
+	 * a context switch should be requested before the interrupt is exited.
+	 *
+	 * @return pdTRUE if the data was successfully sent to the queue, otherwise
+	 * errQUEUE_FULL.
+	 *
+	 * Example usage for buffered IO (where the ISR can obtain more than one value
+	 * per call):
+	   <pre>
+	 void vBufferISR( void )
+	 {
+	 char cIn;
+	 portBASE_TYPE xHigherPriorityTaskWoken;
+
+		// We have not woken a task at the start of the ISR.
+		xHigherPriorityTaskWoken = pdFALSE;
+
+		// Loop until the buffer is empty.
+		do
+		{
+			// Obtain a byte from the buffer.
+			cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+			// Post the byte.
+			xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+		} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+		// Now the buffer is empty we can switch context if necessary.
+		if( xHigherPriorityTaskWoken )
+		{
+			taskYIELD ();
+		}
+	 }
+	 </pre>
+	 *
+	 * \defgroup xQueueSendFromISR xQueueSendFromISR
+	 * \ingroup QueueManagement
+	 */
+#define xQueueSendToBackFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK )
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueSendFromISR(
+										 xQueueHandle pxQueue,
+										 const void *pvItemToQueue,
+										 portBASE_TYPE *pxHigherPriorityTaskWoken
+									);
+	 </pre>
+	 *
+	 * This is a macro that calls xQueueGenericSendFromISR().  It is included
+	 * for backward compatibility with versions of FreeRTOS.org that did not
+	 * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR()
+	 * macros.
+	 *
+	 * Post an item to the back of a queue.  It is safe to use this function from
+	 * within an interrupt service routine.
+	 *
+	 * Items are queued by copy not reference so it is preferable to only
+	 * queue small items, especially when called from an ISR.  In most cases
+	 * it would be preferable to store a pointer to the item being queued.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set
+	 * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+	 * to unblock, and the unblocked task has a priority higher than the currently
+	 * running task.  If xQueueSendFromISR() sets this value to pdTRUE then
+	 * a context switch should be requested before the interrupt is exited.
+	 *
+	 * @return pdTRUE if the data was successfully sent to the queue, otherwise
+	 * errQUEUE_FULL.
+	 *
+	 * Example usage for buffered IO (where the ISR can obtain more than one value
+	 * per call):
+	   <pre>
+	 void vBufferISR( void )
+	 {
+	 char cIn;
+	 portBASE_TYPE xHigherPriorityTaskWoken;
+
+		// We have not woken a task at the start of the ISR.
+		xHigherPriorityTaskWoken = pdFALSE;
+
+		// Loop until the buffer is empty.
+		do
+		{
+			// Obtain a byte from the buffer.
+			cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+			// Post the byte.
+			xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+		} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+		// Now the buffer is empty we can switch context if necessary.
+		if( xHigherPriorityTaskWoken )
+		{
+			// Actual macro used here is port specific.
+			taskYIELD_FROM_ISR ();
+		}
+	 }
+	 </pre>
+	 *
+	 * \defgroup xQueueSendFromISR xQueueSendFromISR
+	 * \ingroup QueueManagement
+	 */
+#define xQueueSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( pxQueue, pvItemToQueue, pxHigherPriorityTaskWoken, queueSEND_TO_BACK )
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueGenericSendFromISR(
+											   xQueueHandle	pxQueue,
+											   const	void	*pvItemToQueue,
+											   portBASE_TYPE	*pxHigherPriorityTaskWoken,
+											   portBASE_TYPE	xCopyPosition
+										   );
+	 </pre>
+	 *
+	 * It is preferred that the macros xQueueSendFromISR(),
+	 * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place
+	 * of calling this function directly.
+	 *
+	 * Post an item on a queue.  It is safe to use this function from within an
+	 * interrupt service routine.
+	 *
+	 * Items are queued by copy not reference so it is preferable to only
+	 * queue small items, especially when called from an ISR.  In most cases
+	 * it would be preferable to store a pointer to the item being queued.
+	 *
+	 * @param xQueue The handle to the queue on which the item is to be posted.
+	 *
+	 * @param pvItemToQueue A pointer to the item that is to be placed on the
+	 * queue.  The size of the items the queue will hold was defined when the
+	 * queue was created, so this many bytes will be copied from pvItemToQueue
+	 * into the queue storage area.
+	 *
+	 * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set
+	 * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task
+	 * to unblock, and the unblocked task has a priority higher than the currently
+	 * running task.  If xQueueGenericSendFromISR() sets this value to pdTRUE then
+	 * a context switch should be requested before the interrupt is exited.
+	 *
+	 * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the
+	 * item at the back of the queue, or queueSEND_TO_FRONT to place the item
+	 * at the front of the queue (for high priority messages).
+	 *
+	 * @return pdTRUE if the data was successfully sent to the queue, otherwise
+	 * errQUEUE_FULL.
+	 *
+	 * Example usage for buffered IO (where the ISR can obtain more than one value
+	 * per call):
+	   <pre>
+	 void vBufferISR( void )
+	 {
+	 char cIn;
+	 portBASE_TYPE xHigherPriorityTaskWokenByPost;
+
+		// We have not woken a task at the start of the ISR.
+		xHigherPriorityTaskWokenByPost = pdFALSE;
+
+		// Loop until the buffer is empty.
+		do
+		{
+			// Obtain a byte from the buffer.
+			cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+			// Post each byte.
+			xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+		} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+		// Now the buffer is empty we can switch context if necessary.  Note that the
+		// name of the yield function required is port specific.
+		if( xHigherPriorityTaskWokenByPost )
+		{
+			taskYIELD_YIELD_FROM_ISR();
+		}
+	 }
+	 </pre>
+	 *
+	 * \defgroup xQueueSendFromISR xQueueSendFromISR
+	 * \ingroup QueueManagement
+	 */
+	signed portBASE_TYPE xQueueGenericSendFromISR(xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition);
+
+	/**
+	 * queue. h
+	 * <pre>
+	 portBASE_TYPE xQueueReceiveFromISR(
+										   xQueueHandle	pxQueue,
+										   void	*pvBuffer,
+										   portBASE_TYPE	*pxTaskWoken
+									   );
+	 * </pre>
+	 *
+	 * Receive an item from a queue.  It is safe to use this function from within an
+	 * interrupt service routine.
+	 *
+	 * @param pxQueue The handle to the queue from which the item is to be
+	 * received.
+	 *
+	 * @param pvBuffer Pointer to the buffer into which the received item will
+	 * be copied.
+	 *
+	 * @param pxTaskWoken A task may be blocked waiting for space to become
+	 * available on the queue.  If xQueueReceiveFromISR causes such a task to
+	 * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will
+	 * remain unchanged.
+	 *
+	 * @return pdTRUE if an item was successfully received from the queue,
+	 * otherwise pdFALSE.
+	 *
+	 * Example usage:
+	   <pre>
+
+	 xQueueHandle xQueue;
+
+	 // Function to create a queue and post some values.
+	 void vAFunction( void *pvParameters )
+	 {
+	 char cValueToPost;
+	 const portTickType xBlockTime = ( portTickType )0xff;
+
+		// Create a queue capable of containing 10 characters.
+		xQueue = xQueueCreate( 10, sizeof( char ) );
+		if( xQueue == 0 )
+		{
+			// Failed to create the queue.
+		}
+
+		// ...
+
+		// Post some characters that will be used within an ISR.  If the queue
+		// is full then this task will block for xBlockTime ticks.
+		cValueToPost = 'a';
+		xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+		cValueToPost = 'b';
+		xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+
+		// ... keep posting characters ... this task may block when the queue
+		// becomes full.
+
+		cValueToPost = 'c';
+		xQueueSend( xQueue, ( void * ) &cValueToPost, xBlockTime );
+	 }
+
+	 // ISR that outputs all the characters received on the queue.
+	 void vISR_Routine( void )
+	 {
+	 portBASE_TYPE xTaskWokenByReceive = pdFALSE;
+	 char cRxedChar;
+
+		while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+		{
+			// A character was received.  Output the character now.
+			vOutputCharacter( cRxedChar );
+
+			// If removing the character from the queue woke the task that was
+			// posting onto the queue cTaskWokenByReceive will have been set to
+			// pdTRUE.  No matter how many times this loop iterates only one
+			// task will be woken.
+		}
+
+		if( cTaskWokenByPost != ( char ) pdFALSE;
+		{
+			taskYIELD ();
+		}
+	 }
+	 </pre>
+	 * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR
+	 * \ingroup QueueManagement
+	 */
+	signed portBASE_TYPE xQueueReceiveFromISR(xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken);
+
+	/*
+	 * Utilities to query queue that are safe to use from an ISR.  These utilities
+	 * should be used only from witin an ISR, or within a critical section.
+	 */
+	signed portBASE_TYPE xQueueIsQueueEmptyFromISR(const xQueueHandle pxQueue);
+	signed portBASE_TYPE xQueueIsQueueFullFromISR(const xQueueHandle pxQueue);
+	unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR(const xQueueHandle pxQueue);
+
+
+	/*
+	 * xQueueAltGenericSend() is an alternative version of xQueueGenericSend().
+	 * Likewise xQueueAltGenericReceive() is an alternative version of
+	 * xQueueGenericReceive().
+	 *
+	 * The source code that implements the alternative (Alt) API is much
+	 * simpler	because it executes everything from within a critical section.
+	 * This is	the approach taken by many other RTOSes, but FreeRTOS.org has the
+	 * preferred fully featured API too.  The fully featured API has more
+	 * complex	code that takes longer to execute, but makes much less use of
+	 * critical sections.  Therefore the alternative API sacrifices interrupt
+	 * responsiveness to gain execution speed, whereas the fully featured API
+	 * sacrifices execution speed to ensure better interrupt responsiveness.
+	 */
+	signed portBASE_TYPE xQueueAltGenericSend(xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition);
+	signed portBASE_TYPE xQueueAltGenericReceive(xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking);
+#define xQueueAltSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_FRONT )
+#define xQueueAltSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueAltGenericSend( xQueue, pvItemToQueue, xTicksToWait, queueSEND_TO_BACK )
+#define xQueueAltReceive( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( xQueue, pvBuffer, xTicksToWait, pdFALSE )
+#define xQueueAltPeek( xQueue, pvBuffer, xTicksToWait ) xQueueAltGenericReceive( xQueue, pvBuffer, xTicksToWait, pdTRUE )
+
+	/*
+	 * The functions defined above are for passing data to and from tasks.  The
+	 * functions below are the equivalents for passing data to and from
+	 * co-routines.
+	 *
+	 * These functions are called from the co-routine macro implementation and
+	 * should not be called directly from application code.  Instead use the macro
+	 * wrappers defined within croutine.h.
+	 */
+	signed portBASE_TYPE xQueueCRSendFromISR(xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken);
+	signed portBASE_TYPE xQueueCRReceiveFromISR(xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken);
+	signed portBASE_TYPE xQueueCRSend(xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait);
+	signed portBASE_TYPE xQueueCRReceive(xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait);
+
+	/*
+	 * For internal use only.  Use xSemaphoreCreateMutex() or
+	 * xSemaphoreCreateCounting() instead of calling these functions directly.
+	 */
+	xQueueHandle xQueueCreateMutex(void);
+	xQueueHandle xQueueCreateCountingSemaphore(unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount);
+
+	/*
+	 * For internal use only.  Use xSemaphoreTakeMutexRecursive() or
+	 * xSemaphoreGiveMutexRecursive() instead of calling these functions directly.
+	 */
+	portBASE_TYPE xQueueTakeMutexRecursive(xQueueHandle xMutex, portTickType xBlockTime);
+	portBASE_TYPE xQueueGiveMutexRecursive(xQueueHandle xMutex);
+
+	/*
+	 * The registry is provided as a means for kernel aware debuggers to
+	 * locate queues, semaphores and mutexes.  Call vQueueAddToRegistry() add
+	 * a queue, semaphore or mutex handle to the registry if you want the handle
+	 * to be available to a kernel aware debugger.  If you are not using a kernel
+	 * aware debugger then this function can be ignored.
+	 *
+	 * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the
+	 * registry can hold.  configQUEUE_REGISTRY_SIZE must be greater than 0
+	 * within FreeRTOSConfig.h for the registry to be available.  Its value
+	 * does not effect the number of queues, semaphores and mutexes that can be
+	 * created - just the number that the registry can hold.
+	 *
+	 * @param xQueue The handle of the queue being added to the registry.  This
+	 * is the handle returned by a call to xQueueCreate().  Semaphore and mutex
+	 * handles can also be passed in here.
+	 *
+	 * @param pcName The name to be associated with the handle.  This is the
+	 * name that the kernel aware debugger will display.
+	 */
+#if configQUEUE_REGISTRY_SIZE > 0
+	void vQueueAddToRegistry(xQueueHandle xQueue, signed char *pcName);
+#endif
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* QUEUE_H */
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/semphr.h b/gyro_board/src/usb/FreeRTOS/include/semphr.h
new file mode 100644
index 0000000..b941518
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/semphr.h
@@ -0,0 +1,711 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef INC_FREERTOS_H
+#error "#include FreeRTOS.h" must appear in source files before "#include semphr.h"
+#endif
+
+#ifndef SEMAPHORE_H
+#define SEMAPHORE_H
+
+#include "queue.h"
+
+typedef xQueueHandle xSemaphoreHandle;
+
+#define semBINARY_SEMAPHORE_QUEUE_LENGTH	( ( unsigned char ) 1 )
+#define semSEMAPHORE_QUEUE_ITEM_LENGTH		( ( unsigned char ) 0 )
+#define semGIVE_BLOCK_TIME					( ( portTickType ) 0 )
+
+
+/**
+ * semphr. h
+ * <pre>vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )</pre>
+ *
+ * <i>Macro</i> that implements a semaphore by using the existing queue mechanism.
+ * The queue length is 1 as this is a binary semaphore.  The data size is 0
+ * as we don't want to actually store any data - we just want to know if the
+ * queue is empty or full.
+ *
+ * This type of semaphore can be used for pure synchronisation between tasks or
+ * between an interrupt and a task.  The semaphore need not be given back once
+ * obtained, so one task/interrupt can continuously 'give' the semaphore while
+ * another continuously 'takes' the semaphore.  For this reason this type of
+ * semaphore does not use a priority inheritance mechanism.  For an alternative
+ * that does use priority inheritance see xSemaphoreCreateMutex().
+ *
+ * @param xSemaphore Handle to the created semaphore.  Should be of type xSemaphoreHandle.
+ *
+ * Example usage:
+ <pre>
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
+ * \ingroup Semaphores
+ */
+#define vSemaphoreCreateBinary( xSemaphore )		{																								\
+														xSemaphore = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH );	\
+														if( xSemaphore != NULL )																	\
+														{																							\
+															xSemaphoreGive( xSemaphore );															\
+														}																							\
+													}
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreTake(
+ *                   xSemaphoreHandle xSemaphore,
+ *                   portTickType xBlockTime
+ *               )</pre>
+ *
+ * <i>Macro</i> to obtain a semaphore.  The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * xSemaphoreCreateCounting().
+ *
+ * @param xSemaphore A handle to the semaphore being taken - obtained when
+ * the semaphore was created.
+ *
+ * @param xBlockTime The time in ticks to wait for the semaphore to become
+ * available.  The macro portTICK_RATE_MS can be used to convert this to a
+ * real time.  A block time of zero can be used to poll the semaphore.  A block
+ * time of portMAX_DELAY can be used to block indefinitely (provided
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).
+ *
+ * @return pdTRUE if the semaphore was obtained.  pdFALSE
+ * if xBlockTime expired without the semaphore becoming available.
+ *
+ * Example usage:
+ <pre>
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreTake xSemaphoreTake
+ * \ingroup Semaphores
+ */
+#define xSemaphoreTake( xSemaphore, xBlockTime )		xQueueGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )
+
+/**
+ * semphr. h
+ * xSemaphoreTakeRecursive(
+ *                          xSemaphoreHandle xMutex,
+ *                          portTickType xBlockTime
+ *                        )
+ *
+ * <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
+ * xSemaphoreCreateRecursiveMutex();
+ *
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
+ * macro to be available.
+ *
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also  'given' the mutex back
+ * exactly five times.
+ *
+ * @param xMutex A handle to the mutex being obtained.  This is the
+ * handle returned by xSemaphoreCreateRecursiveMutex();
+ *
+ * @param xBlockTime The time in ticks to wait for the semaphore to become
+ * available.  The macro portTICK_RATE_MS can be used to convert this to a
+ * real time.  A block time of zero can be used to poll the semaphore.  If
+ * the task already owns the semaphore then xSemaphoreTakeRecursive() will
+ * return immediately no matter what the value of xBlockTime.
+ *
+ * @return pdTRUE if the semaphore was obtained.  pdFALSE if xBlockTime
+ * expired without the semaphore becoming available.
+ *
+ * Example usage:
+ <pre>
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreTakeRecursive( xMutex, xBlockTime )	xQueueTakeMutexRecursive( xMutex, xBlockTime )
+
+
+/*
+ * xSemaphoreAltTake() is an alternative version of xSemaphoreTake().
+ *
+ * The source code that implements the alternative (Alt) API is much
+ * simpler	because it executes everything from within a critical section.
+ * This is	the approach taken by many other RTOSes, but FreeRTOS.org has the
+ * preferred fully featured API too.  The fully featured API has more
+ * complex	code that takes longer to execute, but makes much less use of
+ * critical sections.  Therefore the alternative API sacrifices interrupt
+ * responsiveness to gain execution speed, whereas the fully featured API
+ * sacrifices execution speed to ensure better interrupt responsiveness.
+ */
+#define xSemaphoreAltTake( xSemaphore, xBlockTime )		xQueueAltGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreGive( xSemaphoreHandle xSemaphore )</pre>
+ *
+ * <i>Macro</i> to release a semaphore.  The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or
+ * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake().
+ *
+ * This macro must not be used from an ISR.  See xSemaphoreGiveFromISR () for
+ * an alternative which can be used from an ISR.
+ *
+ * This macro must also not be used on semaphores created using
+ * xSemaphoreCreateRecursiveMutex().
+ *
+ * @param xSemaphore A handle to the semaphore being released.  This is the
+ * handle returned when the semaphore was created.
+ *
+ * @return pdTRUE if the semaphore was released.  pdFALSE if an error occurred.
+ * Semaphores are implemented using queues.  An error can occur if there is
+ * no space on the queue to post a message - indicating that the
+ * semaphore was not first obtained correctly.
+ *
+ * Example usage:
+ <pre>
+ xSemaphoreHandle xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreGive xSemaphoreGive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGive( xSemaphore )		xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )</pre>
+ *
+ * <i>Macro</i> to recursively release, or 'give', a mutex type semaphore.
+ * The mutex must have previously been created using a call to
+ * xSemaphoreCreateRecursiveMutex();
+ *
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this
+ * macro to be available.
+ *
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also  'given' the mutex back
+ * exactly five times.
+ *
+ * @param xMutex A handle to the mutex being released, or 'given'.  This is the
+ * handle returned by xSemaphoreCreateMutex();
+ *
+ * @return pdTRUE if the semaphore was given.
+ *
+ * Example usage:
+ <pre>
+ xSemaphoreHandle xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGiveRecursive( xMutex )	xQueueGiveMutexRecursive( xMutex )
+
+/*
+ * xSemaphoreAltGive() is an alternative version of xSemaphoreGive().
+ *
+ * The source code that implements the alternative (Alt) API is much
+ * simpler	because it executes everything from within a critical section.
+ * This is	the approach taken by many other RTOSes, but FreeRTOS.org has the
+ * preferred fully featured API too.  The fully featured API has more
+ * complex	code that takes longer to execute, but makes much less use of
+ * critical sections.  Therefore the alternative API sacrifices interrupt
+ * responsiveness to gain execution speed, whereas the fully featured API
+ * sacrifices execution speed to ensure better interrupt responsiveness.
+ */
+#define xSemaphoreAltGive( xSemaphore )		xQueueAltGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )
+
+/**
+ * semphr. h
+ * <pre>
+ xSemaphoreGiveFromISR(
+                          xSemaphoreHandle xSemaphore,
+                          signed portBASE_TYPE *pxHigherPriorityTaskWoken
+                      )</pre>
+ *
+ * <i>Macro</i> to  release a semaphore.  The semaphore must have previously been
+ * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting().
+ *
+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())
+ * must not be used with this macro.
+ *
+ * This macro can be used from an ISR.
+ *
+ * @param xSemaphore A handle to the semaphore being released.  This is the
+ * handle returned when the semaphore was created.
+ *
+ * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task
+ * to unblock, and the unblocked task has a priority higher than the currently
+ * running task.  If xSemaphoreGiveFromISR() sets this value to pdTRUE then
+ * a context switch should be requested before the interrupt is exited.
+ *
+ * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL.
+ *
+ * Example usage:
+ <pre>
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT	10
+ xSemaphoreHandle xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static unsigned char ucLocalTickCount = 0;
+ static signed portBASE_TYPE xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
+ * \ingroup Semaphores
+ */
+#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken )			xQueueGenericSendFromISR( ( xQueueHandle ) xSemaphore, NULL, pxHigherPriorityTaskWoken, queueSEND_TO_BACK )
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreHandle xSemaphoreCreateMutex( void )</pre>
+ *
+ * <i>Macro</i> that implements a mutex semaphore by using the existing queue
+ * mechanism.
+ *
+ * Mutexes created using this macro can be accessed using the xSemaphoreTake()
+ * and xSemaphoreGive() macros.  The xSemaphoreTakeRecursive() and
+ * xSemaphoreGiveRecursive() macros should not be used.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See vSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @return xSemaphore Handle to the created mutex semaphore.  Should be of type
+ *		xSemaphoreHandle.
+ *
+ * Example usage:
+ <pre>
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
+ * \ingroup Semaphores
+ */
+#define xSemaphoreCreateMutex() xQueueCreateMutex()
+
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )</pre>
+ *
+ * <i>Macro</i> that implements a recursive mutex by using the existing queue
+ * mechanism.
+ *
+ * Mutexes created using this macro can be accessed using the
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros.  The
+ * xSemaphoreTake() and xSemaphoreGive() macros should not be used.
+ *
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
+ * doesn't become available again until the owner has called
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example,
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will
+ * not be available to any other task until it has also  'given' the mutex back
+ * exactly five times.
+ *
+ * This type of semaphore uses a priority inheritance mechanism so a task
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
+ * semaphore it is no longer required.
+ *
+ * Mutex type semaphores cannot be used from within interrupt service routines.
+ *
+ * See vSemaphoreCreateBinary() for an alternative implementation that can be
+ * used for pure synchronisation (where one task or interrupt always 'gives' the
+ * semaphore and another always 'takes' the semaphore) and from within interrupt
+ * service routines.
+ *
+ * @return xSemaphore Handle to the created mutex semaphore.  Should be of type
+ *		xSemaphoreHandle.
+ *
+ * Example usage:
+ <pre>
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
+ * \ingroup Semaphores
+ */
+#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex()
+
+/**
+ * semphr. h
+ * <pre>xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )</pre>
+ *
+ * <i>Macro</i> that creates a counting semaphore by using the existing
+ * queue mechanism.
+ *
+ * Counting semaphores are typically used for two things:
+ *
+ * 1) Counting events.
+ *
+ *    In this usage scenario an event handler will 'give' a semaphore each time
+ *    an event occurs (incrementing the semaphore count value), and a handler
+ *    task will 'take' a semaphore each time it processes an event
+ *    (decrementing the semaphore count value).  The count value is therefore
+ *    the difference between the number of events that have occurred and the
+ *    number that have been processed.  In this case it is desirable for the
+ *    initial count value to be zero.
+ *
+ * 2) Resource management.
+ *
+ *    In this usage scenario the count value indicates the number of resources
+ *    available.  To obtain control of a resource a task must first obtain a
+ *    semaphore - decrementing the semaphore count value.  When the count value
+ *    reaches zero there are no free resources.  When a task finishes with the
+ *    resource it 'gives' the semaphore back - incrementing the semaphore count
+ *    value.  In this case it is desirable for the initial count value to be
+ *    equal to the maximum count value, indicating that all resources are free.
+ *
+ * @param uxMaxCount The maximum count value that can be reached.  When the
+ *        semaphore reaches this value it can no longer be 'given'.
+ *
+ * @param uxInitialCount The count value assigned to the semaphore when it is
+ *        created.
+ *
+ * @return Handle to the created semaphore.  Null if the semaphore could not be
+ *         created.
+ *
+ * Example usage:
+ <pre>
+ xSemaphoreHandle xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ xSemaphoreHandle xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ </pre>
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
+ * \ingroup Semaphores
+ */
+#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount )
+
+
+#endif /* SEMAPHORE_H */
+
+
diff --git a/gyro_board/src/usb/FreeRTOS/include/task.h b/gyro_board/src/usb/FreeRTOS/include/task.h
new file mode 100644
index 0000000..a8d8a62
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/include/task.h
@@ -0,0 +1,1261 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+#ifndef INC_FREERTOS_H
+#error "#include FreeRTOS.h" must appear in source files before "#include task.h"
+#endif
+
+
+
+#ifndef TASK_H
+#define TASK_H
+
+#include "portable.h"
+#include "list.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	/*-----------------------------------------------------------
+	 * MACROS AND DEFINITIONS
+	 *----------------------------------------------------------*/
+
+#define tskKERNEL_VERSION_NUMBER "V6.0.4"
+
+	/**
+	 * task. h
+	 *
+	 * Type by which tasks are referenced.  For example, a call to xTaskCreate
+	 * returns (via a pointer parameter) an xTaskHandle variable that can then
+	 * be used as a parameter to vTaskDelete to delete the task.
+	 *
+	 * \page xTaskHandle xTaskHandle
+	 * \ingroup Tasks
+	 */
+	typedef void * xTaskHandle;
+
+	/*
+	 * Used internally only.
+	 */
+	typedef struct xTIME_OUT {
+		portBASE_TYPE xOverflowCount;
+		portTickType  xTimeOnEntering;
+	} xTimeOutType;
+
+	/*
+	 * Defines the memory ranges allocated to the task when an MPU is used.
+	 */
+	typedef struct xMEMORY_REGION {
+		void *pvBaseAddress;
+		unsigned long ulLengthInBytes;
+		unsigned long ulParameters;
+	} xMemoryRegion;
+
+	/*
+	 * Parameters required to create an MPU protected task.
+	 */
+	typedef struct xTASK_PARAMTERS {
+		pdTASK_CODE pvTaskCode;
+		const signed char * const pcName;
+		unsigned short usStackDepth;
+		void *pvParameters;
+		unsigned portBASE_TYPE uxPriority;
+		portSTACK_TYPE *puxStackBuffer;
+		xMemoryRegion xRegions[ portNUM_CONFIGURABLE_REGIONS ];
+	} xTaskParameters;
+
+	/*
+	 * Defines the priority used by the idle task.  This must not be modified.
+	 *
+	 * \ingroup TaskUtils
+	 */
+#define tskIDLE_PRIORITY			( ( unsigned portBASE_TYPE ) 0 )
+
+	/**
+	 * task. h
+	 *
+	 * Macro for forcing a context switch.
+	 *
+	 * \page taskYIELD taskYIELD
+	 * \ingroup SchedulerControl
+	 */
+#define taskYIELD()					portYIELD()
+
+	/**
+	 * task. h
+	 *
+	 * Macro to mark the start of a critical code region.  Preemptive context
+	 * switches cannot occur when in a critical region.
+	 *
+	 * NOTE: This may alter the stack (depending on the portable implementation)
+	 * so must be used with care!
+	 *
+	 * \page taskENTER_CRITICAL taskENTER_CRITICAL
+	 * \ingroup SchedulerControl
+	 */
+#define taskENTER_CRITICAL()		portENTER_CRITICAL()
+
+	/**
+	 * task. h
+	 *
+	 * Macro to mark the end of a critical code region.  Preemptive context
+	 * switches cannot occur when in a critical region.
+	 *
+	 * NOTE: This may alter the stack (depending on the portable implementation)
+	 * so must be used with care!
+	 *
+	 * \page taskEXIT_CRITICAL taskEXIT_CRITICAL
+	 * \ingroup SchedulerControl
+	 */
+#define taskEXIT_CRITICAL()			portEXIT_CRITICAL()
+
+	/**
+	 * task. h
+	 *
+	 * Macro to disable all maskable interrupts.
+	 *
+	 * \page taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS
+	 * \ingroup SchedulerControl
+	 */
+#define taskDISABLE_INTERRUPTS()	portDISABLE_INTERRUPTS()
+
+	/**
+	 * task. h
+	 *
+	 * Macro to enable microcontroller interrupts.
+	 *
+	 * \page taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS
+	 * \ingroup SchedulerControl
+	 */
+#define taskENABLE_INTERRUPTS()		portENABLE_INTERRUPTS()
+
+	/* Definitions returned by xTaskGetSchedulerState(). */
+#define taskSCHEDULER_NOT_STARTED	0
+#define taskSCHEDULER_RUNNING		1
+#define taskSCHEDULER_SUSPENDED		2
+
+	/*-----------------------------------------------------------
+	 * TASK CREATION API
+	 *----------------------------------------------------------*/
+
+	/**
+	 * task. h
+	 *<pre>
+	 portBASE_TYPE xTaskCreate(
+								  pdTASK_CODE pvTaskCode,
+								  const char * const pcName,
+								  unsigned short usStackDepth,
+								  void *pvParameters,
+								  unsigned portBASE_TYPE uxPriority,
+								  xTaskHandle *pvCreatedTask
+							  );</pre>
+	 *
+	 * Create a new task and add it to the list of tasks that are ready to run.
+	 *
+	 * xTaskCreate() can only be used to create a task that has unrestricted
+	 * access to the entire microcontroller memory map.  Systems that include MPU
+	 * support can alternatively create an MPU constrained task using
+	 * xTaskCreateRestricted().
+	 *
+	 * @param pvTaskCode Pointer to the task entry function.  Tasks
+	 * must be implemented to never return (i.e. continuous loop).
+	 *
+	 * @param pcName A descriptive name for the task.  This is mainly used to
+	 * facilitate debugging.  Max length defined by tskMAX_TASK_NAME_LEN - default
+	 * is 16.
+	 *
+	 * @param usStackDepth The size of the task stack specified as the number of
+	 * variables the stack can hold - not the number of bytes.  For example, if
+	 * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes
+	 * will be allocated for stack storage.
+	 *
+	 * @param pvParameters Pointer that will be used as the parameter for the task
+	 * being created.
+	 *
+	 * @param uxPriority The priority at which the task should run.  Systems that
+	 * include MPU support can optionally create tasks in a privileged (system)
+	 * mode by setting bit portPRIVILEGE_BIT of the priority parameter.  For
+	 * example, to create a privileged task at priority 2 the uxPriority parameter
+	 * should be set to ( 2 | portPRIVILEGE_BIT ).
+	 *
+	 * @param pvCreatedTask Used to pass back a handle by which the created task
+	 * can be referenced.
+	 *
+	 * @return pdPASS if the task was successfully created and added to a ready
+	 * list, otherwise an error code defined in the file errors. h
+	 *
+	 * Example usage:
+	   <pre>
+	 // Task to be created.
+	 void vTaskCode( void * pvParameters )
+	 {
+		 for( ;; )
+		 {
+			 // Task code goes here.
+		 }
+	 }
+
+	 // Function that creates a task.
+	 void vOtherFunction( void )
+	 {
+	 static unsigned char ucParameterToPass;
+	 xTaskHandle xHandle;
+
+		 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
+		 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
+		 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+		 // the new task attempts to access it.
+		 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+
+		 // Use the handle to delete the task.
+		 vTaskDelete( xHandle );
+	 }
+	   </pre>
+	 * \defgroup xTaskCreate xTaskCreate
+	 * \ingroup Tasks
+	 */
+#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ) )
+
+	/**
+	 * task. h
+	 *<pre>
+	 portBASE_TYPE xTaskCreateRestricted( xTaskParameters *pxTaskDefinition, xTaskHandle *pxCreatedTask );</pre>
+	 *
+	 * xTaskCreateRestricted() should only be used in systems that include an MPU
+	 * implementation.
+	 *
+	 * Create a new task and add it to the list of tasks that are ready to run.
+	 * The function parameters define the memory regions and associated access
+	 * permissions allocated to the task.
+	 *
+	 * @param pxTaskDefinition Pointer to a structure that contains a member
+	 * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API
+	 * documentation) plus an optional stack buffer and the memory region
+	 * definitions.
+	 *
+	 * @param pxCreatedTask Used to pass back a handle by which the created task
+	 * can be referenced.
+	 *
+	 * @return pdPASS if the task was successfully created and added to a ready
+	 * list, otherwise an error code defined in the file errors. h
+	 *
+	 * Example usage:
+	   <pre>
+	// Create an xTaskParameters structure that defines the task to be created.
+	static const xTaskParameters xCheckTaskParameters =
+	{
+		vATask,		// pvTaskCode - the function that implements the task.
+		"ATask",	// pcName - just a text name for the task to assist debugging.
+		100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+		NULL,		// pvParameters - passed into the task function as the function parameters.
+		( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+		cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+		// xRegions - Allocate up to three separate memory regions for access by
+		// the task, with appropriate access permissions.  Different processors have
+		// different memory alignment requirements - refer to the FreeRTOS documentation
+		// for full information.
+		{
+			// Base address					Length	Parameters
+	        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+	        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+	        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+		}
+	};
+
+	int main( void )
+	{
+	xTaskHandle xHandle;
+
+		// Create a task from the const structure defined above.  The task handle
+		// is requested (the second parameter is not NULL) but in this case just for
+		// demonstration purposes as its not actually used.
+		xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+		// Start the scheduler.
+		vTaskStartScheduler();
+
+		// Will only get here if there was insufficient memory to create the idle
+		// task.
+		for( ;; );
+	}
+	   </pre>
+	 * \defgroup xTaskCreateRestricted xTaskCreateRestricted
+	 * \ingroup Tasks
+	 */
+#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) )
+
+	/**
+	 * task. h
+	 *<pre>
+	 void vTaskAllocateMPURegions( xTaskHandle xTask, const xMemoryRegion * const pxRegions );</pre>
+	 *
+	 * Memory regions are assigned to a restricted task when the task is created by
+	 * a call to xTaskCreateRestricted().  These regions can be redefined using
+	 * vTaskAllocateMPURegions().
+	 *
+	 * @param xTask The handle of the task being updated.
+	 *
+	 * @param xRegions A pointer to an xMemoryRegion structure that contains the
+	 * new memory region definitions.
+	 *
+	 * Example usage:
+	   <pre>
+	// Define an array of xMemoryRegion structures that configures an MPU region
+	// allowing read/write access for 1024 bytes starting at the beginning of the
+	// ucOneKByte array.  The other two of the maximum 3 definable regions are
+	// unused so set to zero.
+	static const xMemoryRegion xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+	{
+		// Base address		Length		Parameters
+		{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
+		{ 0,				0,			0 },
+		{ 0,				0,			0 }
+	};
+
+	void vATask( void *pvParameters )
+	{
+		// This task was created such that it has access to certain regions of
+		// memory as defined by the MPU configuration.  At some point it is
+		// desired that these MPU regions are replaced with that defined in the
+		// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
+		// for this purpose.  NULL is used as the task handle to indicate that this
+		// function should modify the MPU regions of the calling task.
+		vTaskAllocateMPURegions( NULL, xAltRegions );
+
+		// Now the task can continue its function, but from this point on can only
+		// access its stack and the ucOneKByte array (unless any other statically
+		// defined or shared regions have been declared elsewhere).
+	}
+	   </pre>
+	 * \defgroup xTaskCreateRestricted xTaskCreateRestricted
+	 * \ingroup Tasks
+	 */
+	void vTaskAllocateMPURegions(xTaskHandle xTask, const xMemoryRegion * const pxRegions) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>void vTaskDelete( xTaskHandle pxTask );</pre>
+	 *
+	 * INCLUDE_vTaskDelete must be defined as 1 for this function to be available.
+	 * See the configuration section for more information.
+	 *
+	 * Remove a task from the RTOS real time kernels management.  The task being
+	 * deleted will be removed from all ready, blocked, suspended and event lists.
+	 *
+	 * NOTE:  The idle task is responsible for freeing the kernel allocated
+	 * memory from tasks that have been deleted.  It is therefore important that
+	 * the idle task is not starved of microcontroller processing time if your
+	 * application makes any calls to vTaskDelete ().  Memory allocated by the
+	 * task code is not automatically freed, and should be freed before the task
+	 * is deleted.
+	 *
+	 * See the demo application file death.c for sample code that utilises
+	 * vTaskDelete ().
+	 *
+	 * @param pxTask The handle of the task to be deleted.  Passing NULL will
+	 * cause the calling task to be deleted.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vOtherFunction( void )
+	 {
+	 xTaskHandle xHandle;
+
+		 // Create the task, storing the handle.
+		 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+		 // Use the handle to delete the task.
+		 vTaskDelete( xHandle );
+	 }
+	   </pre>
+	 * \defgroup vTaskDelete vTaskDelete
+	 * \ingroup Tasks
+	 */
+	void vTaskDelete(xTaskHandle pxTask) PRIVILEGED_FUNCTION;
+
+
+	/*-----------------------------------------------------------
+	 * TASK CONTROL API
+	 *----------------------------------------------------------*/
+
+	/**
+	 * task. h
+	 * <pre>void vTaskDelay( portTickType xTicksToDelay );</pre>
+	 *
+	 * Delay a task for a given number of ticks.  The actual time that the
+	 * task remains blocked depends on the tick rate.  The constant
+	 * portTICK_RATE_MS can be used to calculate real time from the tick
+	 * rate - with the resolution of one tick period.
+	 *
+	 * INCLUDE_vTaskDelay must be defined as 1 for this function to be available.
+	 * See the configuration section for more information.
+	 *
+	 *
+	 * vTaskDelay() specifies a time at which the task wishes to unblock relative to
+	 * the time at which vTaskDelay() is called.  For example, specifying a block
+	 * period of 100 ticks will cause the task to unblock 100 ticks after
+	 * vTaskDelay() is called.  vTaskDelay() does not therefore provide a good method
+	 * of controlling the frequency of a cyclical task as the path taken through the
+	 * code, as well as other task and interrupt activity, will effect the frequency
+	 * at which vTaskDelay() gets called and therefore the time at which the task
+	 * next executes.  See vTaskDelayUntil() for an alternative API function designed
+	 * to facilitate fixed frequency execution.  It does this by specifying an
+	 * absolute time (rather than a relative time) at which the calling task should
+	 * unblock.
+	 *
+	 * @param xTicksToDelay The amount of time, in tick periods, that
+	 * the calling task should block.
+	 *
+	 * Example usage:
+
+	 void vTaskFunction( void * pvParameters )
+	 {
+	 void vTaskFunction( void * pvParameters )
+	 {
+	 // Block for 500ms.
+	 const portTickType xDelay = 500 / portTICK_RATE_MS;
+
+		 for( ;; )
+		 {
+			 // Simply toggle the LED every 500ms, blocking between each toggle.
+			 vToggleLED();
+			 vTaskDelay( xDelay );
+		 }
+	 }
+
+	 * \defgroup vTaskDelay vTaskDelay
+	 * \ingroup TaskCtrl
+	 */
+	void vTaskDelay(portTickType xTicksToDelay) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>void vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );</pre>
+	 *
+	 * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available.
+	 * See the configuration section for more information.
+	 *
+	 * Delay a task until a specified time.  This function can be used by cyclical
+	 * tasks to ensure a constant execution frequency.
+	 *
+	 * This function differs from vTaskDelay () in one important aspect:  vTaskDelay () will
+	 * cause a task to block for the specified number of ticks from the time vTaskDelay () is
+	 * called.  It is therefore difficult to use vTaskDelay () by itself to generate a fixed
+	 * execution frequency as the time between a task starting to execute and that task
+	 * calling vTaskDelay () may not be fixed [the task may take a different path though the
+	 * code between calls, or may get interrupted or preempted a different number of times
+	 * each time it executes].
+	 *
+	 * Whereas vTaskDelay () specifies a wake time relative to the time at which the function
+	 * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to
+	 * unblock.
+	 *
+	 * The constant portTICK_RATE_MS can be used to calculate real time from the tick
+	 * rate - with the resolution of one tick period.
+	 *
+	 * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the
+	 * task was last unblocked.  The variable must be initialised with the current time
+	 * prior to its first use (see the example below).  Following this the variable is
+	 * automatically updated within vTaskDelayUntil ().
+	 *
+	 * @param xTimeIncrement The cycle time period.  The task will be unblocked at
+	 * time *pxPreviousWakeTime + xTimeIncrement.  Calling vTaskDelayUntil with the
+	 * same xTimeIncrement parameter value will cause the task to execute with
+	 * a fixed interface period.
+	 *
+	 * Example usage:
+	   <pre>
+	 // Perform an action every 10 ticks.
+	 void vTaskFunction( void * pvParameters )
+	 {
+	 portTickType xLastWakeTime;
+	 const portTickType xFrequency = 10;
+
+		 // Initialise the xLastWakeTime variable with the current time.
+		 xLastWakeTime = xTaskGetTickCount ();
+		 for( ;; )
+		 {
+			 // Wait for the next cycle.
+			 vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+			 // Perform action here.
+		 }
+	 }
+	   </pre>
+	 * \defgroup vTaskDelayUntil vTaskDelayUntil
+	 * \ingroup TaskCtrl
+	 */
+	void vTaskDelayUntil(portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );</pre>
+	 *
+	 * INCLUDE_xTaskPriorityGet must be defined as 1 for this function to be available.
+	 * See the configuration section for more information.
+	 *
+	 * Obtain the priority of any task.
+	 *
+	 * @param pxTask Handle of the task to be queried.  Passing a NULL
+	 * handle results in the priority of the calling task being returned.
+	 *
+	 * @return The priority of pxTask.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vAFunction( void )
+	 {
+	 xTaskHandle xHandle;
+
+		 // Create a task, storing the handle.
+		 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+		 // ...
+
+		 // Use the handle to obtain the priority of the created task.
+		 // It was created with tskIDLE_PRIORITY, but may have changed
+		 // it itself.
+		 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+		 {
+			 // The task has changed it's priority.
+		 }
+
+		 // ...
+
+		 // Is our priority higher than the created task?
+		 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+		 {
+			 // Our priority (obtained using NULL handle) is higher.
+		 }
+	 }
+	   </pre>
+	 * \defgroup uxTaskPriorityGet uxTaskPriorityGet
+	 * \ingroup TaskCtrl
+	 */
+	unsigned portBASE_TYPE uxTaskPriorityGet(xTaskHandle pxTask) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );</pre>
+	 *
+	 * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available.
+	 * See the configuration section for more information.
+	 *
+	 * Set the priority of any task.
+	 *
+	 * A context switch will occur before the function returns if the priority
+	 * being set is higher than the currently executing task.
+	 *
+	 * @param pxTask Handle to the task for which the priority is being set.
+	 * Passing a NULL handle results in the priority of the calling task being set.
+	 *
+	 * @param uxNewPriority The priority to which the task will be set.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vAFunction( void )
+	 {
+	 xTaskHandle xHandle;
+
+		 // Create a task, storing the handle.
+		 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+		 // ...
+
+		 // Use the handle to raise the priority of the created task.
+		 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+		 // ...
+
+		 // Use a NULL handle to raise our priority to the same value.
+		 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+	 }
+	   </pre>
+	 * \defgroup vTaskPrioritySet vTaskPrioritySet
+	 * \ingroup TaskCtrl
+	 */
+	void vTaskPrioritySet(xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>void vTaskSuspend( xTaskHandle pxTaskToSuspend );</pre>
+	 *
+	 * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
+	 * See the configuration section for more information.
+	 *
+	 * Suspend any task.  When suspended a task will never get any microcontroller
+	 * processing time, no matter what its priority.
+	 *
+	 * Calls to vTaskSuspend are not accumulative -
+	 * i.e. calling vTaskSuspend () twice on the same task still only requires one
+	 * call to vTaskResume () to ready the suspended task.
+	 *
+	 * @param pxTaskToSuspend Handle to the task being suspended.  Passing a NULL
+	 * handle will cause the calling task to be suspended.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vAFunction( void )
+	 {
+	 xTaskHandle xHandle;
+
+		 // Create a task, storing the handle.
+		 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+		 // ...
+
+		 // Use the handle to suspend the created task.
+		 vTaskSuspend( xHandle );
+
+		 // ...
+
+		 // The created task will not run during this period, unless
+		 // another task calls vTaskResume( xHandle ).
+
+		 //...
+
+
+		 // Suspend ourselves.
+		 vTaskSuspend( NULL );
+
+		 // We cannot get here unless another task calls vTaskResume
+		 // with our handle as the parameter.
+	 }
+	   </pre>
+	 * \defgroup vTaskSuspend vTaskSuspend
+	 * \ingroup TaskCtrl
+	 */
+	void vTaskSuspend(xTaskHandle pxTaskToSuspend) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>void vTaskResume( xTaskHandle pxTaskToResume );</pre>
+	 *
+	 * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available.
+	 * See the configuration section for more information.
+	 *
+	 * Resumes a suspended task.
+	 *
+	 * A task that has been suspended by one of more calls to vTaskSuspend ()
+	 * will be made available for running again by a single call to
+	 * vTaskResume ().
+	 *
+	 * @param pxTaskToResume Handle to the task being readied.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vAFunction( void )
+	 {
+	 xTaskHandle xHandle;
+
+		 // Create a task, storing the handle.
+		 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+		 // ...
+
+		 // Use the handle to suspend the created task.
+		 vTaskSuspend( xHandle );
+
+		 // ...
+
+		 // The created task will not run during this period, unless
+		 // another task calls vTaskResume( xHandle ).
+
+		 //...
+
+
+		 // Resume the suspended task ourselves.
+		 vTaskResume( xHandle );
+
+		 // The created task will once again get microcontroller processing
+		 // time in accordance with it priority within the system.
+	 }
+	   </pre>
+	 * \defgroup vTaskResume vTaskResume
+	 * \ingroup TaskCtrl
+	 */
+	void vTaskResume(xTaskHandle pxTaskToResume) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>void xTaskResumeFromISR( xTaskHandle pxTaskToResume );</pre>
+	 *
+	 * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be
+	 * available.  See the configuration section for more information.
+	 *
+	 * An implementation of vTaskResume() that can be called from within an ISR.
+	 *
+	 * A task that has been suspended by one of more calls to vTaskSuspend ()
+	 * will be made available for running again by a single call to
+	 * xTaskResumeFromISR ().
+	 *
+	 * @param pxTaskToResume Handle to the task being readied.
+	 *
+	 * \defgroup vTaskResumeFromISR vTaskResumeFromISR
+	 * \ingroup TaskCtrl
+	 */
+	portBASE_TYPE xTaskResumeFromISR(xTaskHandle pxTaskToResume) PRIVILEGED_FUNCTION;
+
+	/*-----------------------------------------------------------
+	 * SCHEDULER CONTROL
+	 *----------------------------------------------------------*/
+
+	/**
+	 * task. h
+	 * <pre>void vTaskStartScheduler( void );</pre>
+	 *
+	 * Starts the real time kernel tick processing.  After calling the kernel
+	 * has control over which tasks are executed and when.  This function
+	 * does not return until an executing task calls vTaskEndScheduler ().
+	 *
+	 * At least one task should be created via a call to xTaskCreate ()
+	 * before calling vTaskStartScheduler ().  The idle task is created
+	 * automatically when the first application task is created.
+	 *
+	 * See the demo application file main.c for an example of creating
+	 * tasks and starting the kernel.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vAFunction( void )
+	 {
+		 // Create at least one task before starting the kernel.
+		 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+		 // Start the real time kernel with preemption.
+		 vTaskStartScheduler ();
+
+		 // Will not get here unless a task calls vTaskEndScheduler ()
+	 }
+	   </pre>
+	 *
+	 * \defgroup vTaskStartScheduler vTaskStartScheduler
+	 * \ingroup SchedulerControl
+	 */
+	void vTaskStartScheduler(void) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>void vTaskEndScheduler( void );</pre>
+	 *
+	 * Stops the real time kernel tick.  All created tasks will be automatically
+	 * deleted and multitasking (either preemptive or cooperative) will
+	 * stop.  Execution then resumes from the point where vTaskStartScheduler ()
+	 * was called, as if vTaskStartScheduler () had just returned.
+	 *
+	 * See the demo application file main. c in the demo/PC directory for an
+	 * example that uses vTaskEndScheduler ().
+	 *
+	 * vTaskEndScheduler () requires an exit function to be defined within the
+	 * portable layer (see vPortEndScheduler () in port. c for the PC port).  This
+	 * performs hardware specific operations such as stopping the kernel tick.
+	 *
+	 * vTaskEndScheduler () will cause all of the resources allocated by the
+	 * kernel to be freed - but will not free resources allocated by application
+	 * tasks.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vTaskCode( void * pvParameters )
+	 {
+		 for( ;; )
+		 {
+			 // Task code goes here.
+
+			 // At some point we want to end the real time kernel processing
+			 // so call ...
+			 vTaskEndScheduler ();
+		 }
+	 }
+
+	 void vAFunction( void )
+	 {
+		 // Create at least one task before starting the kernel.
+		 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+		 // Start the real time kernel with preemption.
+		 vTaskStartScheduler ();
+
+		 // Will only get here when the vTaskCode () task has called
+		 // vTaskEndScheduler ().  When we get here we are back to single task
+		 // execution.
+	 }
+	   </pre>
+	 *
+	 * \defgroup vTaskEndScheduler vTaskEndScheduler
+	 * \ingroup SchedulerControl
+	 */
+	void vTaskEndScheduler(void) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>void vTaskSuspendAll( void );</pre>
+	 *
+	 * Suspends all real time kernel activity while keeping interrupts (including the
+	 * kernel tick) enabled.
+	 *
+	 * After calling vTaskSuspendAll () the calling task will continue to execute
+	 * without risk of being swapped out until a call to xTaskResumeAll () has been
+	 * made.
+	 *
+	 * API functions that have the potential to cause a context switch (for example,
+	 * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler
+	 * is suspended.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vTask1( void * pvParameters )
+	 {
+		 for( ;; )
+		 {
+			 // Task code goes here.
+
+			 // ...
+
+			 // At some point the task wants to perform a long operation during
+			 // which it does not want to get swapped out.  It cannot use
+			 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+			 // operation may cause interrupts to be missed - including the
+			 // ticks.
+
+			 // Prevent the real time kernel swapping out the task.
+			 vTaskSuspendAll ();
+
+			 // Perform the operation here.  There is no need to use critical
+			 // sections as we have all the microcontroller processing time.
+			 // During this time interrupts will still operate and the kernel
+			 // tick count will be maintained.
+
+			 // ...
+
+			 // The operation is complete.  Restart the kernel.
+			 xTaskResumeAll ();
+		 }
+	 }
+	   </pre>
+	 * \defgroup vTaskSuspendAll vTaskSuspendAll
+	 * \ingroup SchedulerControl
+	 */
+	void vTaskSuspendAll(void) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>char xTaskResumeAll( void );</pre>
+	 *
+	 * Resumes real time kernel activity following a call to vTaskSuspendAll ().
+	 * After a call to vTaskSuspendAll () the kernel will take control of which
+	 * task is executing at any time.
+	 *
+	 * @return If resuming the scheduler caused a context switch then pdTRUE is
+	 *		  returned, otherwise pdFALSE is returned.
+	 *
+	 * Example usage:
+	   <pre>
+	 void vTask1( void * pvParameters )
+	 {
+		 for( ;; )
+		 {
+			 // Task code goes here.
+
+			 // ...
+
+			 // At some point the task wants to perform a long operation during
+			 // which it does not want to get swapped out.  It cannot use
+			 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+			 // operation may cause interrupts to be missed - including the
+			 // ticks.
+
+			 // Prevent the real time kernel swapping out the task.
+			 vTaskSuspendAll ();
+
+			 // Perform the operation here.  There is no need to use critical
+			 // sections as we have all the microcontroller processing time.
+			 // During this time interrupts will still operate and the real
+			 // time kernel tick count will be maintained.
+
+			 // ...
+
+			 // The operation is complete.  Restart the kernel.  We want to force
+			 // a context switch - but there is no point if resuming the scheduler
+			 // caused a context switch already.
+			 if( !xTaskResumeAll () )
+			 {
+				  taskYIELD ();
+			 }
+		 }
+	 }
+	   </pre>
+	 * \defgroup xTaskResumeAll xTaskResumeAll
+	 * \ingroup SchedulerControl
+	 */
+	signed portBASE_TYPE xTaskResumeAll(void) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <pre>signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask );</pre>
+	 *
+	 * Utility task that simply returns pdTRUE if the task referenced by xTask is
+	 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
+	 * is in any other state.
+	 *
+	 */
+	signed portBASE_TYPE xTaskIsTaskSuspended(xTaskHandle xTask) PRIVILEGED_FUNCTION;
+
+	/*-----------------------------------------------------------
+	 * TASK UTILITIES
+	 *----------------------------------------------------------*/
+
+	/**
+	 * task. h
+	 * <PRE>volatile portTickType xTaskGetTickCount( void );</PRE>
+	 *
+	 * @return The count of ticks since vTaskStartScheduler was called.
+	 *
+	 * \page xTaskGetTickCount xTaskGetTickCount
+	 * \ingroup TaskUtils
+	 */
+	portTickType xTaskGetTickCount(void) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <PRE>unsigned short uxTaskGetNumberOfTasks( void );</PRE>
+	 *
+	 * @return The number of tasks that the real time kernel is currently managing.
+	 * This includes all ready, blocked and suspended tasks.  A task that
+	 * has been deleted but not yet freed by the idle task will also be
+	 * included in the count.
+	 *
+	 * \page uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks
+	 * \ingroup TaskUtils
+	 */
+	unsigned portBASE_TYPE uxTaskGetNumberOfTasks(void) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <PRE>void vTaskList( char *pcWriteBuffer );</PRE>
+	 *
+	 * configUSE_TRACE_FACILITY must be defined as 1 for this function to be
+	 * available.  See the configuration section for more information.
+	 *
+	 * NOTE: This function will disable interrupts for its duration.  It is
+	 * not intended for normal application runtime use but as a debug aid.
+	 *
+	 * Lists all the current tasks, along with their current state and stack
+	 * usage high water mark.
+	 *
+	 * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or
+	 * suspended ('S').
+	 *
+	 * @param pcWriteBuffer A buffer into which the above mentioned details
+	 * will be written, in ascii form.  This buffer is assumed to be large
+	 * enough to contain the generated report.  Approximately 40 bytes per
+	 * task should be sufficient.
+	 *
+	 * \page vTaskList vTaskList
+	 * \ingroup TaskUtils
+	 */
+	void vTaskList(signed char *pcWriteBuffer) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <PRE>void vTaskGetRunTimeStats( char *pcWriteBuffer );</PRE>
+	 *
+	 * configGENERATE_RUN_TIME_STATS must be defined as 1 for this function
+	 * to be available.  The application must also then provide definitions
+	 * for portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and
+	 * portGET_RUN_TIME_COUNTER_VALUE to configure a peripheral timer/counter
+	 * and return the timers current count value respectively.  The counter
+	 * should be at least 10 times the frequency of the tick count.
+	 *
+	 * NOTE: This function will disable interrupts for its duration.  It is
+	 * not intended for normal application runtime use but as a debug aid.
+	 *
+	 * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total
+	 * accumulated execution time being stored for each task.  The resolution
+	 * of the accumulated time value depends on the frequency of the timer
+	 * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro.
+	 * Calling vTaskGetRunTimeStats() writes the total execution time of each
+	 * task into a buffer, both as an absolute count value and as a percentage
+	 * of the total system execution time.
+	 *
+	 * @param pcWriteBuffer A buffer into which the execution times will be
+	 * written, in ascii form.  This buffer is assumed to be large enough to
+	 * contain the generated report.  Approximately 40 bytes per task should
+	 * be sufficient.
+	 *
+	 * \page vTaskGetRunTimeStats vTaskGetRunTimeStats
+	 * \ingroup TaskUtils
+	 */
+	void vTaskGetRunTimeStats(signed char *pcWriteBuffer) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <PRE>void vTaskStartTrace( char * pcBuffer, unsigned portBASE_TYPE uxBufferSize );</PRE>
+	 *
+	 * Starts a real time kernel activity trace.  The trace logs the identity of
+	 * which task is running when.
+	 *
+	 * The trace file is stored in binary format.  A separate DOS utility called
+	 * convtrce.exe is used to convert this into a tab delimited text file which
+	 * can be viewed and plotted in a spread sheet.
+	 *
+	 * @param pcBuffer The buffer into which the trace will be written.
+	 *
+	 * @param ulBufferSize The size of pcBuffer in bytes.  The trace will continue
+	 * until either the buffer in full, or ulTaskEndTrace () is called.
+	 *
+	 * \page vTaskStartTrace vTaskStartTrace
+	 * \ingroup TaskUtils
+	 */
+	void vTaskStartTrace(signed char * pcBuffer, unsigned long ulBufferSize) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task. h
+	 * <PRE>unsigned long ulTaskEndTrace( void );</PRE>
+	 *
+	 * Stops a kernel activity trace.  See vTaskStartTrace ().
+	 *
+	 * @return The number of bytes that have been written into the trace buffer.
+	 *
+	 * \page usTaskEndTrace usTaskEndTrace
+	 * \ingroup TaskUtils
+	 */
+	unsigned long ulTaskEndTrace(void) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task.h
+	 * <PRE>unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask );</PRE>
+	 *
+	 * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for
+	 * this function to be available.
+	 *
+	 * Returns the high water mark of the stack associated with xTask.  That is,
+	 * the minimum free stack space there has been (in bytes) since the task
+	 * started.  The smaller the returned number the closer the task has come
+	 * to overflowing its stack.
+	 *
+	 * @param xTask Handle of the task associated with the stack to be checked.
+	 * Set xTask to NULL to check the stack of the calling task.
+	 *
+	 * @return The smallest amount of free stack space there has been (in bytes)
+	 * since the task referenced by xTask was created.
+	 */
+	unsigned portBASE_TYPE uxTaskGetStackHighWaterMark(xTaskHandle xTask) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task.h
+	 * <pre>void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );</pre>
+	 *
+	 * Sets pxHookFunction to be the task hook function used by the task xTask.
+	 * Passing xTask as NULL has the effect of setting the calling tasks hook
+	 * function.
+	 */
+	void vTaskSetApplicationTaskTag(xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task.h
+	 * <pre>void xTaskGetApplicationTaskTag( xTaskHandle xTask );</pre>
+	 *
+	 * Returns the pxHookFunction value assigned to the task xTask.
+	 */
+	pdTASK_HOOK_CODE xTaskGetApplicationTaskTag(xTaskHandle xTask) PRIVILEGED_FUNCTION;
+
+	/**
+	 * task.h
+	 * <pre>portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction );</pre>
+	 *
+	 * Calls the hook function associated with xTask.  Passing xTask as NULL has
+	 * the effect of calling the Running tasks (the calling task) hook function.
+	 *
+	 * pvParameter is passed to the hook function for the task to interpret as it
+	 * wants.
+	 */
+	portBASE_TYPE xTaskCallApplicationTaskHook(xTaskHandle xTask, void *pvParameter) PRIVILEGED_FUNCTION;
+
+
+	/*-----------------------------------------------------------
+	 * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
+	 *----------------------------------------------------------*/
+
+	/*
+	 * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS ONLY
+	 * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
+	 * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+	 *
+	 * Called from the real time kernel tick (either preemptive or cooperative),
+	 * this increments the tick count and checks if any tasks that are blocked
+	 * for a finite period required removing from a blocked list and placing on
+	 * a ready list.
+	 */
+	void vTaskIncrementTick(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS AN
+	 * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+	 *
+	 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
+	 *
+	 * Removes the calling task from the ready list and places it both
+	 * on the list of tasks waiting for a particular event, and the
+	 * list of delayed tasks.  The task will be removed from both lists
+	 * and replaced on the ready list should either the event occur (and
+	 * there be no higher priority tasks waiting on the same event) or
+	 * the delay period expires.
+	 *
+	 * @param pxEventList The list containing tasks that are blocked waiting
+	 * for the event to occur.
+	 *
+	 * @param xTicksToWait The maximum amount of time that the task should wait
+	 * for the event to occur.  This is specified in kernel ticks,the constant
+	 * portTICK_RATE_MS can be used to convert kernel ticks into a real time
+	 * period.
+	 */
+	void vTaskPlaceOnEventList(const xList * const pxEventList, portTickType xTicksToWait) PRIVILEGED_FUNCTION;
+
+	/*
+	 * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS AN
+	 * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+	 *
+	 * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED.
+	 *
+	 * Removes a task from both the specified event list and the list of blocked
+	 * tasks, and places it on a ready queue.
+	 *
+	 * xTaskRemoveFromEventList () will be called if either an event occurs to
+	 * unblock a task, or the block timeout period expires.
+	 *
+	 * @return pdTRUE if the task being removed has a higher priority than the task
+	 * making the call, otherwise pdFALSE.
+	 */
+	signed portBASE_TYPE xTaskRemoveFromEventList(const xList * const pxEventList) PRIVILEGED_FUNCTION;
+
+	/*
+	 * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS AN
+	 * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+	 *
+	 * INCLUDE_vTaskCleanUpResources and INCLUDE_vTaskSuspend must be defined as 1
+	 * for this function to be available.
+	 * See the configuration section for more information.
+	 *
+	 * Empties the ready and delayed queues of task control blocks, freeing the
+	 * memory allocated for the task control block and task stacks as it goes.
+	 */
+	void vTaskCleanUpResources(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS ONLY
+	 * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
+	 * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
+	 *
+	 * Sets the pointer to the current TCB to the TCB of the highest priority task
+	 * that is ready to run.
+	 */
+	void vTaskSwitchContext(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Return the handle of the calling task.
+	 */
+	xTaskHandle xTaskGetCurrentTaskHandle(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Capture the current time status for future reference.
+	 */
+	void vTaskSetTimeOutState(xTimeOutType * const pxTimeOut) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Compare the time status now with that previously captured to see if the
+	 * timeout has expired.
+	 */
+	portBASE_TYPE xTaskCheckForTimeOut(xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Shortcut used by the queue implementation to prevent unnecessary call to
+	 * taskYIELD();
+	 */
+	void vTaskMissedYield(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Returns the scheduler state as taskSCHEDULER_RUNNING,
+	 * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED.
+	 */
+	portBASE_TYPE xTaskGetSchedulerState(void) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Raises the priority of the mutex holder to that of the calling task should
+	 * the mutex holder have a priority less than the calling task.
+	 */
+	void vTaskPriorityInherit(xTaskHandle * const pxMutexHolder) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Set the priority of a task back to its proper priority in the case that it
+	 * inherited a higher priority while it was holding a semaphore.
+	 */
+	void vTaskPriorityDisinherit(xTaskHandle * const pxMutexHolder) PRIVILEGED_FUNCTION;
+
+	/*
+	 * Generic version of the task creation function which is in turn called by the
+	 * xTaskCreate() and xTaskCreateRestricted() macros.
+	 */
+	signed portBASE_TYPE xTaskGenericCreate(pdTASK_CODE pvTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions) PRIVILEGED_FUNCTION;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* TASK_H */
+
+
+
diff --git a/gyro_board/src/usb/FreeRTOS/list.c b/gyro_board/src/usb/FreeRTOS/list.c
new file mode 100644
index 0000000..0b88791
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/list.c
@@ -0,0 +1,186 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+#include <stdlib.h>
+#include "FreeRTOS.h"
+#include "list.h"
+
+/*-----------------------------------------------------------
+ * PUBLIC LIST API documented in list.h
+ *----------------------------------------------------------*/
+
+void vListInitialise(xList *pxList)
+{
+	/* The list structure contains a list item which is used to mark the
+	end of the list.  To initialise the list the list end is inserted
+	as the only list entry. */
+	pxList->pxIndex = (xListItem *) & (pxList->xListEnd);
+
+	/* The list end value is the highest possible value in the list to
+	ensure it remains at the end of the list. */
+	pxList->xListEnd.xItemValue = portMAX_DELAY;
+
+	/* The list end next and previous pointers point to itself so we know
+	when the list is empty. */
+	pxList->xListEnd.pxNext = (xListItem *) & (pxList->xListEnd);
+	pxList->xListEnd.pxPrevious = (xListItem *) & (pxList->xListEnd);
+
+	pxList->uxNumberOfItems = 0;
+}
+/*-----------------------------------------------------------*/
+
+void vListInitialiseItem(xListItem *pxItem)
+{
+	/* Make sure the list item is not recorded as being on a list. */
+	pxItem->pvContainer = NULL;
+}
+/*-----------------------------------------------------------*/
+
+void vListInsertEnd(xList *pxList, xListItem *pxNewListItem)
+{
+	volatile xListItem * pxIndex;
+
+	/* Insert a new list item into pxList, but rather than sort the list,
+	makes the new list item the last item to be removed by a call to
+	pvListGetOwnerOfNextEntry.  This means it has to be the item pointed to by
+	the pxIndex member. */
+	pxIndex = pxList->pxIndex;
+
+	pxNewListItem->pxNext = pxIndex->pxNext;
+	pxNewListItem->pxPrevious = pxList->pxIndex;
+	pxIndex->pxNext->pxPrevious = (volatile xListItem *) pxNewListItem;
+	pxIndex->pxNext = (volatile xListItem *) pxNewListItem;
+	pxList->pxIndex = (volatile xListItem *) pxNewListItem;
+
+	/* Remember which list the item is in. */
+	pxNewListItem->pvContainer = (void *) pxList;
+
+	(pxList->uxNumberOfItems)++;
+}
+/*-----------------------------------------------------------*/
+
+void vListInsert(xList *pxList, xListItem *pxNewListItem)
+{
+	volatile xListItem *pxIterator;
+	portTickType xValueOfInsertion;
+
+	/* Insert the new list item into the list, sorted in ulListItem order. */
+	xValueOfInsertion = pxNewListItem->xItemValue;
+
+	/* If the list already contains a list item with the same item value then
+	the new list item should be placed after it.  This ensures that TCB's which
+	are stored in ready lists (all of which have the same ulListItem value)
+	get an equal share of the CPU.  However, if the xItemValue is the same as
+	the back marker the iteration loop below will not end.  This means we need
+	to guard against this by checking the value first and modifying the
+	algorithm slightly if necessary. */
+	if (xValueOfInsertion == portMAX_DELAY) {
+		pxIterator = pxList->xListEnd.pxPrevious;
+	} else {
+		/* *** NOTE ***********************************************************
+		If you find your application is crashing here then likely causes are:
+			1) Stack overflow -
+			   see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
+			2) Incorrect interrupt priority assignment, especially on Cortex M3
+			   parts where numerically high priority values denote low actual
+			   interrupt priories, which can seem counter intuitive.  See
+			   configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html
+			3) Calling an API function from within a critical section or when
+			   the scheduler is suspended.
+			4) Using a queue or semaphore before it has been initialised or
+			   before the scheduler has been started (are interrupts firing
+			   before vTaskStartScheduler() has been called?).
+		See http://www.freertos.org/FAQHelp.html for more tips.
+		**********************************************************************/
+
+		for (pxIterator = (xListItem *) & (pxList->xListEnd); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext) {
+			/* There is nothing to do here, we are just iterating to the
+			wanted insertion position. */
+		}
+	}
+
+	pxNewListItem->pxNext = pxIterator->pxNext;
+	pxNewListItem->pxNext->pxPrevious = (volatile xListItem *) pxNewListItem;
+	pxNewListItem->pxPrevious = pxIterator;
+	pxIterator->pxNext = (volatile xListItem *) pxNewListItem;
+
+	/* Remember which list the item is in.  This allows fast removal of the
+	item later. */
+	pxNewListItem->pvContainer = (void *) pxList;
+
+	(pxList->uxNumberOfItems)++;
+}
+/*-----------------------------------------------------------*/
+
+void vListRemove(xListItem *pxItemToRemove)
+{
+	xList * pxList;
+
+	pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
+	pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
+
+	/* The list item knows which list it is in.  Obtain the list from the list
+	item. */
+	pxList = (xList *) pxItemToRemove->pvContainer;
+
+	/* Make sure the index is left pointing to a valid item. */
+	if (pxList->pxIndex == pxItemToRemove) {
+		pxList->pxIndex = pxItemToRemove->pxPrevious;
+	}
+
+	pxItemToRemove->pvContainer = NULL;
+	(pxList->uxNumberOfItems)--;
+}
+/*-----------------------------------------------------------*/
+
diff --git a/gyro_board/src/usb/FreeRTOS/portable/GCC/ARM_CM3/port.c b/gyro_board/src/usb/FreeRTOS/portable/GCC/ARM_CM3/port.c
new file mode 100644
index 0000000..fb55c72
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/portable/GCC/ARM_CM3/port.c
@@ -0,0 +1,280 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*-----------------------------------------------------------
+ * Implementation of functions defined in portable.h for the ARM CM3 port.
+ *----------------------------------------------------------*/
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
+defined.  The value should also ensure backward compatibility.
+FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
+#ifndef configKERNEL_INTERRUPT_PRIORITY
+#define configKERNEL_INTERRUPT_PRIORITY 255
+#endif
+
+/* Constants required to manipulate the NVIC. */
+#define portNVIC_SYSTICK_CTRL		( ( volatile unsigned long *) 0xe000e010 )
+#define portNVIC_SYSTICK_LOAD		( ( volatile unsigned long *) 0xe000e014 )
+#define portNVIC_INT_CTRL			( ( volatile unsigned long *) 0xe000ed04 )
+#define portNVIC_SYSPRI2			( ( volatile unsigned long *) 0xe000ed20 )
+#define portNVIC_SYSTICK_CLK		0x00000004
+#define portNVIC_SYSTICK_INT		0x00000002
+#define portNVIC_SYSTICK_ENABLE		0x00000001
+#define portNVIC_PENDSVSET			0x10000000
+#define portNVIC_PENDSV_PRI			( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )
+#define portNVIC_SYSTICK_PRI		( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )
+
+/* Constants required to set up the initial stack. */
+#define portINITIAL_XPSR			( 0x01000000 )
+
+/* The priority used by the kernel is assigned to a variable to make access
+from inline assembler easier. */
+const unsigned long ulKernelPriority = configKERNEL_INTERRUPT_PRIORITY;
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. */
+static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
+
+/*
+ * Setup the timer to generate the tick interrupts.
+ */
+static void prvSetupTimerInterrupt(void);
+
+/*
+ * Exception handlers.
+ */
+void xPortPendSVHandler(void) __attribute__((naked));
+void xPortSysTickHandler(void);
+void vPortSVCHandler(void) __attribute__((naked));
+
+/*
+ * Start first task is a separate function so it can be tested in isolation.
+ */
+void vPortStartFirstTask(void) __attribute__((naked));
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+portSTACK_TYPE *pxPortInitialiseStack(portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters)
+{
+	/* Simulate the stack frame as it would be created by a context switch
+	interrupt. */
+	pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+	*pxTopOfStack = portINITIAL_XPSR;	/* xPSR */
+	pxTopOfStack--;
+	*pxTopOfStack = (portSTACK_TYPE) pxCode;	/* PC */
+	pxTopOfStack--;
+	*pxTopOfStack = 0;	/* LR */
+	pxTopOfStack -= 5;	/* R12, R3, R2 and R1. */
+	*pxTopOfStack = (portSTACK_TYPE) pvParameters;	/* R0 */
+	pxTopOfStack -= 8;	/* R11, R10, R9, R8, R7, R6, R5 and R4. */
+
+	return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+void vPortSVCHandler(void)
+{
+	__asm volatile(
+	        "	ldr	r3, pxCurrentTCBConst2		\n" /* Restore the context. */
+	        "	ldr r1, [r3]					\n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
+	        "	ldr r0, [r1]					\n" /* The first item in pxCurrentTCB is the task top of stack. */
+	        "	ldmia r0!, {r4-r11}				\n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
+	        "	msr psp, r0						\n" /* Restore the task stack pointer. */
+	        "	mov r0, #0 						\n"
+	        "	msr	basepri, r0					\n"
+	        "	orr r14, #0xd					\n"
+	        "	bx r14							\n"
+	        "									\n"
+	        "	.align 2						\n"
+	        "pxCurrentTCBConst2: .word pxCurrentTCB				\n"
+	);
+}
+/*-----------------------------------------------------------*/
+
+void vPortStartFirstTask(void)
+{
+	__asm volatile(
+	        " ldr r0, =0xE000ED08 	\n" /* Use the NVIC offset register to locate the stack. */
+	        " ldr r0, [r0] 			\n"
+	        " ldr r0, [r0] 			\n"
+	        " msr msp, r0			\n" /* Set the msp back to the start of the stack. */
+	        " svc 0					\n" /* System call to start first task. */
+	);
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+portBASE_TYPE xPortStartScheduler(void)
+{
+	/* Make PendSV, CallSV and SysTick the same priroity as the kernel. */
+	*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;
+	*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;
+
+	/* Start the timer that generates the tick ISR.  Interrupts are disabled
+	here already. */
+	prvSetupTimerInterrupt();
+
+	/* Initialise the critical nesting count ready for the first task. */
+	uxCriticalNesting = 0;
+
+	/* Start the first task. */
+	vPortStartFirstTask();
+
+	/* Should not get here! */
+	return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler(void)
+{
+	/* It is unlikely that the CM3 port will require this function as there
+	is nothing to return to.  */
+}
+/*-----------------------------------------------------------*/
+
+void vPortYieldFromISR(void)
+{
+	/* Set a PendSV to request a context switch. */
+	*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical(void)
+{
+	portDISABLE_INTERRUPTS();
+	uxCriticalNesting++;
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical(void)
+{
+	uxCriticalNesting--;
+	if (uxCriticalNesting == 0) {
+		portENABLE_INTERRUPTS();
+	}
+}
+/*-----------------------------------------------------------*/
+
+void xPortPendSVHandler(void)
+{
+	/* This is a naked function. */
+
+	__asm volatile
+	(
+	        "	mrs r0, psp							\n"
+	        "										\n"
+	        "	ldr	r3, pxCurrentTCBConst			\n" /* Get the location of the current TCB. */
+	        "	ldr	r2, [r3]						\n"
+	        "										\n"
+	        "	stmdb r0!, {r4-r11}					\n" /* Save the remaining registers. */
+	        "	str r0, [r2]						\n" /* Save the new top of stack into the first member of the TCB. */
+	        "										\n"
+	        "	stmdb sp!, {r3, r14}				\n"
+	        "	mov r0, %0							\n"
+	        "	msr basepri, r0						\n"
+	        "	bl vTaskSwitchContext				\n"
+	        "	mov r0, #0							\n"
+	        "	msr basepri, r0						\n"
+	        "	ldmia sp!, {r3, r14}				\n"
+	        "										\n"	/* Restore the context, including the critical nesting count. */
+	        "	ldr r1, [r3]						\n"
+	        "	ldr r0, [r1]						\n" /* The first item in pxCurrentTCB is the task top of stack. */
+	        "	ldmia r0!, {r4-r11}					\n" /* Pop the registers. */
+	        "	msr psp, r0							\n"
+	        "	bx r14								\n"
+	        "										\n"
+	        "	.align 2							\n"
+	        "pxCurrentTCBConst: .word pxCurrentTCB	\n"
+	        ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
+	);
+}
+/*-----------------------------------------------------------*/
+
+void xPortSysTickHandler(void)
+{
+	unsigned long ulDummy;
+
+	/* If using preemption, also force a context switch. */
+#if configUSE_PREEMPTION == 1
+	*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
+#endif
+
+	ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		vTaskIncrementTick();
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR(ulDummy);
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+void prvSetupTimerInterrupt(void)
+{
+	/* Configure SysTick to interrupt at the requested rate. */
+	*(portNVIC_SYSTICK_LOAD) = (configCPU_CLOCK_HZ / configTICK_RATE_HZ) - 1UL;
+	*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
+}
+/*-----------------------------------------------------------*/
+
diff --git a/gyro_board/src/usb/FreeRTOS/portable/GCC/ARM_CM3/portmacro.h b/gyro_board/src/usb/FreeRTOS/portable/GCC/ARM_CM3/portmacro.h
new file mode 100644
index 0000000..35c57ac
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/portable/GCC/ARM_CM3/portmacro.h
@@ -0,0 +1,157 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+	/*-----------------------------------------------------------
+	 * Port specific definitions.
+	 *
+	 * The settings in this file configure FreeRTOS correctly for the
+	 * given hardware and compiler.
+	 *
+	 * These settings should not be altered.
+	 *-----------------------------------------------------------
+	 */
+
+	/* Type definitions. */
+#define portCHAR		char
+#define portFLOAT		float
+#define portDOUBLE		double
+#define portLONG		long
+#define portSHORT		short
+#define portSTACK_TYPE	unsigned portLONG
+#define portBASE_TYPE	long
+
+#if( configUSE_16_BIT_TICKS == 1 )
+	typedef unsigned portSHORT portTickType;
+#define portMAX_DELAY ( portTickType ) 0xffff
+#else
+	typedef unsigned portLONG portTickType;
+#define portMAX_DELAY ( portTickType ) 0xffffffff
+#endif
+	/*-----------------------------------------------------------*/
+
+	/* Architecture specifics. */
+#define portSTACK_GROWTH			( -1 )
+#define portTICK_RATE_MS			( ( portTickType ) 1000 / configTICK_RATE_HZ )
+#define portBYTE_ALIGNMENT			8
+	/*-----------------------------------------------------------*/
+
+
+	/* Scheduler utilities. */
+	extern void vPortYieldFromISR(void);
+
+#define portYIELD()					vPortYieldFromISR()
+
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
+	/*-----------------------------------------------------------*/
+
+
+	/* Critical section management. */
+
+	/*
+	 * Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other
+	 * registers.  r0 is clobbered.
+	 */
+#define portSET_INTERRUPT_MASK()						\
+	__asm volatile										\
+	(													\
+		"	mov r0, %0								\n"	\
+		"	msr basepri, r0							\n" \
+		::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0"	\
+	)
+
+	/*
+	 * Set basepri back to 0 without effective other registers.
+	 * r0 is clobbered.
+	 */
+#define portCLEAR_INTERRUPT_MASK()			\
+	__asm volatile							\
+	(										\
+		"	mov r0, #0					\n"	\
+		"	msr basepri, r0				\n"	\
+		:::"r0"								\
+	)
+
+#define portSET_INTERRUPT_MASK_FROM_ISR()		0;portSET_INTERRUPT_MASK()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	portCLEAR_INTERRUPT_MASK();(void)x
+
+
+	extern void vPortEnterCritical(void);
+	extern void vPortExitCritical(void);
+
+#define portDISABLE_INTERRUPTS()	portSET_INTERRUPT_MASK()
+#define portENABLE_INTERRUPTS()		portCLEAR_INTERRUPT_MASK()
+#define portENTER_CRITICAL()		vPortEnterCritical()
+#define portEXIT_CRITICAL()			vPortExitCritical()
+	/*-----------------------------------------------------------*/
+
+	/* Task function macros as described on the FreeRTOS.org WEB site. */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+
+#define portNOP()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */
+
diff --git a/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_1.c b/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_1.c
new file mode 100644
index 0000000..5ccda33
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_1.c
@@ -0,0 +1,152 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public 
+    License and the FreeRTOS license exception along with FreeRTOS; if not it 
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained 
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+/*
+ * The simplest possible implementation of pvPortMalloc().  Note that this
+ * implementation does NOT allow allocated memory to be freed again.
+ *
+ * See heap_2.c and heap_3.c for alternative implementations, and the memory
+ * management pages of http://www.FreeRTOS.org for more information.
+ */
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* Allocate the memory for the heap.  The struct is used to force byte
+alignment without using any non-portable code. */
+static union xRTOS_HEAP
+{
+	#if portBYTE_ALIGNMENT == 8
+		volatile portDOUBLE dDummy;
+	#else
+		volatile unsigned long ulDummy;
+	#endif	
+	unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
+} xHeap;
+
+static size_t xNextFreeByte = ( size_t ) 0;
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+void *pvReturn = NULL; 
+
+	/* Ensure that blocks are always aligned to the required number of bytes. */
+	#if portBYTE_ALIGNMENT != 1
+		if( xWantedSize & portBYTE_ALIGNMENT_MASK )
+		{
+			/* Byte alignment required. */
+			xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
+		}
+	#endif
+
+	vTaskSuspendAll();
+	{
+		/* Check there is enough room left for the allocation. */
+		if( ( ( xNextFreeByte + xWantedSize ) < configTOTAL_HEAP_SIZE ) &&
+			( ( xNextFreeByte + xWantedSize ) > xNextFreeByte )	)/* Check for overflow. */
+		{
+			/* Return the next free byte then increment the index past this
+			block. */
+			pvReturn = &( xHeap.ucHeap[ xNextFreeByte ] );
+			xNextFreeByte += xWantedSize;			
+		}	
+	}
+	xTaskResumeAll();
+	
+	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
+	{
+		if( pvReturn == NULL )
+		{
+			extern void vApplicationMallocFailedHook( void );
+			vApplicationMallocFailedHook();
+		}
+	}
+	#endif	
+
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+	/* Memory cannot be freed using this scheme.  See heap_2.c and heap_3.c 
+	for alternative implementations, and the memory management pages of 
+	http://www.FreeRTOS.org for more information. */
+	( void ) pv;
+}
+/*-----------------------------------------------------------*/
+
+void vPortInitialiseBlocks( void )
+{
+	/* Only required when static memory is not cleared. */
+	xNextFreeByte = ( size_t ) 0;
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetFreeHeapSize( void )
+{
+	return ( configTOTAL_HEAP_SIZE - xNextFreeByte );
+}
+
+
+
diff --git a/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_2.c b/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_2.c
new file mode 100644
index 0000000..77e13b8
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_2.c
@@ -0,0 +1,278 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public 
+    License and the FreeRTOS license exception along with FreeRTOS; if not it 
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained 
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/*
+ * A sample implementation of pvPortMalloc() and vPortFree() that permits
+ * allocated blocks to be freed, but does not combine adjacent free blocks
+ * into a single larger block.
+ *
+ * See heap_1.c and heap_3.c for alternative implementations, and the memory
+ * management pages of http://www.FreeRTOS.org for more information.
+ */
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/* Allocate the memory for the heap.  The struct is used to force byte
+alignment without using any non-portable code. */
+static union xRTOS_HEAP
+{
+	#if portBYTE_ALIGNMENT == 8
+		volatile portDOUBLE dDummy;
+	#else
+		volatile unsigned long ulDummy;
+	#endif
+	unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
+} xHeap;
+
+/* Define the linked list structure.  This is used to link free blocks in order
+of their size. */
+typedef struct A_BLOCK_LINK
+{
+	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<< The next free block in the list. */
+	size_t xBlockSize;						/*<< The size of the free block. */
+} xBlockLink;
+
+
+static const unsigned short  heapSTRUCT_SIZE	= ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) );
+#define heapMINIMUM_BLOCK_SIZE	( ( size_t ) ( heapSTRUCT_SIZE * 2 ) )
+
+/* Create a couple of list links to mark the start and end of the list. */
+static xBlockLink xStart, xEnd;
+
+/* Keeps track of the number of free bytes remaining, but says nothing about
+fragmentation. */
+static size_t xFreeBytesRemaining = configTOTAL_HEAP_SIZE;
+
+/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */
+
+/*
+ * Insert a block into the list of free blocks - which is ordered by size of
+ * the block.  Small blocks at the start of the list and large blocks at the end
+ * of the list.
+ */
+#define prvInsertBlockIntoFreeList( pxBlockToInsert )								\
+{																					\
+xBlockLink *pxIterator;																\
+size_t xBlockSize;																	\
+																					\
+	xBlockSize = pxBlockToInsert->xBlockSize;										\
+																					\
+	/* Iterate through the list until a block is found that has a larger size */	\
+	/* than the block we are inserting. */											\
+	for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock )	\
+	{																				\
+		/* There is nothing to do here - just iterate to the correct position. */	\
+	}																				\
+																					\
+	/* Update the list to include the block being inserted in the correct */		\
+	/* position. */																	\
+	pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;					\
+	pxIterator->pxNextFreeBlock = pxBlockToInsert;									\
+}
+/*-----------------------------------------------------------*/
+
+#define prvHeapInit()																\
+{																					\
+xBlockLink *pxFirstFreeBlock;														\
+																					\
+	/* xStart is used to hold a pointer to the first item in the list of free */	\
+	/* blocks.  The void cast is used to prevent compiler warnings. */				\
+	xStart.pxNextFreeBlock = ( void * ) xHeap.ucHeap;								\
+	xStart.xBlockSize = ( size_t ) 0;												\
+																					\
+	/* xEnd is used to mark the end of the list of free blocks. */					\
+	xEnd.xBlockSize = configTOTAL_HEAP_SIZE;										\
+	xEnd.pxNextFreeBlock = NULL;													\
+																					\
+	/* To start with there is a single free block that is sized to take up the		\
+	entire heap space. */															\
+	pxFirstFreeBlock = ( void * ) xHeap.ucHeap;										\
+	pxFirstFreeBlock->xBlockSize = configTOTAL_HEAP_SIZE;							\
+	pxFirstFreeBlock->pxNextFreeBlock = &xEnd;										\
+}
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
+static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE;
+void *pvReturn = NULL;
+
+	vTaskSuspendAll();
+	{
+		/* If this is the first call to malloc then the heap will require
+		initialisation to setup the list of free blocks. */
+		if( xHeapHasBeenInitialised == pdFALSE )
+		{
+			prvHeapInit();
+			xHeapHasBeenInitialised = pdTRUE;
+		}
+
+		/* The wanted size is increased so it can contain a xBlockLink
+		structure in addition to the requested amount of bytes. */
+		if( xWantedSize > 0 )
+		{
+			xWantedSize += heapSTRUCT_SIZE;
+
+			/* Ensure that blocks are always aligned to the required number of bytes. */
+			if( xWantedSize & portBYTE_ALIGNMENT_MASK )
+			{
+				/* Byte alignment required. */
+				xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
+			}
+		}
+
+		if( ( xWantedSize > 0 ) && ( xWantedSize < configTOTAL_HEAP_SIZE ) )
+		{
+			/* Blocks are stored in byte order - traverse the list from the start
+			(smallest) block until one of adequate size is found. */
+			pxPreviousBlock = &xStart;
+			pxBlock = xStart.pxNextFreeBlock;
+			while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock ) )
+			{
+				pxPreviousBlock = pxBlock;
+				pxBlock = pxBlock->pxNextFreeBlock;
+			}
+
+			/* If we found the end marker then a block of adequate size was not found. */
+			if( pxBlock != &xEnd )
+			{
+				/* Return the memory space - jumping over the xBlockLink structure
+				at its start. */
+				pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );
+
+				/* This block is being returned for use so must be taken our of the
+				list of free blocks. */
+				pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
+
+				/* If the block is larger than required it can be split into two. */
+				if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
+				{
+					/* This block is to be split into two.  Create a new block
+					following the number of bytes requested. The void cast is
+					used to prevent byte alignment warnings from the compiler. */
+					pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize );
+
+					/* Calculate the sizes of two blocks split from the single
+					block. */
+					pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
+					pxBlock->xBlockSize = xWantedSize;
+
+					/* Insert the new block into the list of free blocks. */
+					prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
+				}
+				
+				xFreeBytesRemaining -= xWantedSize;
+			}
+		}
+	}
+	xTaskResumeAll();
+
+	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
+	{
+		if( pvReturn == NULL )
+		{
+			extern void vApplicationMallocFailedHook( void );
+			vApplicationMallocFailedHook();
+		}
+	}
+	#endif
+
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+unsigned char *puc = ( unsigned char * ) pv;
+xBlockLink *pxLink;
+
+	if( pv )
+	{
+		/* The memory being freed will have an xBlockLink structure immediately
+		before it. */
+		puc -= heapSTRUCT_SIZE;
+
+		/* This casting is to keep the compiler from issuing warnings. */
+		pxLink = ( void * ) puc;
+
+		vTaskSuspendAll();
+		{
+			/* Add this block to the list of free blocks. */
+			prvInsertBlockIntoFreeList( ( ( xBlockLink * ) pxLink ) );
+			xFreeBytesRemaining += pxLink->xBlockSize;
+		}
+		xTaskResumeAll();
+	}
+}
+/*-----------------------------------------------------------*/
+
+size_t xPortGetFreeHeapSize( void )
+{
+	return xFreeBytesRemaining;
+}
+/*-----------------------------------------------------------*/
+
+void vPortInitialiseBlocks( void )
+{
+	/* This just exists to keep the linker quiet. */
+}
diff --git a/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_3.c b/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_3.c
new file mode 100644
index 0000000..643f750
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/portable/MemMang/heap_3.c
@@ -0,0 +1,117 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public 
+    License and the FreeRTOS license exception along with FreeRTOS; if not it 
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained 
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+/*
+ * Implementation of pvPortMalloc() and vPortFree() that relies on the
+ * compilers own malloc() and free() implementations.
+ *
+ * This file can only be used if the linker is configured to to generate
+ * a heap memory area.
+ *
+ * See heap_2.c and heap_1.c for alternative implementations, and the memory
+ * management pages of http://www.FreeRTOS.org for more information.
+ */
+
+#include <stdlib.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/*-----------------------------------------------------------*/
+
+void *pvPortMalloc( size_t xWantedSize )
+{
+void *pvReturn;
+
+	vTaskSuspendAll();
+	{
+		pvReturn = malloc( xWantedSize );
+	}
+	xTaskResumeAll();
+
+	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
+	{
+		if( pvReturn == NULL )
+		{
+			extern void vApplicationMallocFailedHook( void );
+			vApplicationMallocFailedHook();
+		}
+	}
+	#endif
+	
+	return pvReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vPortFree( void *pv )
+{
+	if( pv )
+	{
+		vTaskSuspendAll();
+		{
+			free( pv );
+		}
+		xTaskResumeAll();
+	}
+}
+
+
+
diff --git a/gyro_board/src/usb/FreeRTOS/queue.c b/gyro_board/src/usb/FreeRTOS/queue.c
new file mode 100644
index 0000000..acd6119
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/queue.c
@@ -0,0 +1,1302 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "croutine.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/*-----------------------------------------------------------
+ * PUBLIC LIST API documented in list.h
+ *----------------------------------------------------------*/
+
+/* Constants used with the cRxLock and cTxLock structure members. */
+#define queueUNLOCKED					( ( signed portBASE_TYPE ) -1 )
+#define queueLOCKED_UNMODIFIED			( ( signed portBASE_TYPE ) 0 )
+
+#define queueERRONEOUS_UNBLOCK			( -1 )
+
+/* For internal use only. */
+#define	queueSEND_TO_BACK				( 0 )
+#define	queueSEND_TO_FRONT				( 1 )
+
+/* Effectively make a union out of the xQUEUE structure. */
+#define pxMutexHolder					pcTail
+#define uxQueueType						pcHead
+#define uxRecursiveCallCount			pcReadFrom
+#define queueQUEUE_IS_MUTEX				NULL
+
+/* Semaphores do not actually store or copy data, so have an items size of
+zero. */
+#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )
+#define queueDONT_BLOCK					 ( ( portTickType ) 0 )
+#define queueMUTEX_GIVE_BLOCK_TIME		 ( ( portTickType ) 0 )
+
+/*
+ * Definition of the queue used by the scheduler.
+ * Items are queued by copy, not reference.
+ */
+typedef struct QueueDefinition {
+	signed char *pcHead;				/*< Points to the beginning of the queue storage area. */
+	signed char *pcTail;				/*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
+
+	signed char *pcWriteTo;				/*< Points to the free next place in the storage area. */
+	signed char *pcReadFrom;			/*< Points to the last place that a queued item was read from. */
+
+	xList xTasksWaitingToSend;				/*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
+	xList xTasksWaitingToReceive;			/*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */
+
+	volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
+	unsigned portBASE_TYPE uxLength;		/*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
+	unsigned portBASE_TYPE uxItemSize;		/*< The size of each items that the queue will hold. */
+
+	signed portBASE_TYPE xRxLock;			/*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
+	signed portBASE_TYPE xTxLock;			/*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */
+
+} xQUEUE;
+/*-----------------------------------------------------------*/
+
+/*
+ * Inside this file xQueueHandle is a pointer to a xQUEUE structure.
+ * To keep the definition private the API header file defines it as a
+ * pointer to void.
+ */
+typedef xQUEUE * xQueueHandle;
+
+/*
+ * Prototypes for public functions are included here so we don't have to
+ * include the API header file (as it defines xQueueHandle differently).  These
+ * functions are documented in the API header file.
+ */
+xQueueHandle xQueueCreate(unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueGenericSend(xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition) PRIVILEGED_FUNCTION;
+unsigned portBASE_TYPE uxQueueMessagesWaiting(const xQueueHandle pxQueue) PRIVILEGED_FUNCTION;
+void vQueueDelete(xQueueHandle xQueue) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueGenericSendFromISR(xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueGenericReceive(xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueReceiveFromISR(xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken) PRIVILEGED_FUNCTION;
+xQueueHandle xQueueCreateMutex(void) PRIVILEGED_FUNCTION;
+xQueueHandle xQueueCreateCountingSemaphore(unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount) PRIVILEGED_FUNCTION;
+portBASE_TYPE xQueueTakeMutexRecursive(xQueueHandle xMutex, portTickType xBlockTime) PRIVILEGED_FUNCTION;
+portBASE_TYPE xQueueGiveMutexRecursive(xQueueHandle xMutex) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueAltGenericSend(xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueAltGenericReceive(xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR(const xQueueHandle pxQueue) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueIsQueueFullFromISR(const xQueueHandle pxQueue) PRIVILEGED_FUNCTION;
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR(const xQueueHandle pxQueue) PRIVILEGED_FUNCTION;
+
+/*
+ * Co-routine queue functions differ from task queue functions.  Co-routines are
+ * an optional component.
+ */
+#if configUSE_CO_ROUTINES == 1
+signed portBASE_TYPE xQueueCRSendFromISR(xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueCRReceiveFromISR(xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueCRSend(xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait) PRIVILEGED_FUNCTION;
+signed portBASE_TYPE xQueueCRReceive(xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * The queue registry is just a means for kernel aware debuggers to locate
+ * queue structures.  It has no other purpose so is an optional component.
+ */
+#if configQUEUE_REGISTRY_SIZE > 0
+
+/* The type stored within the queue registry array.  This allows a name
+to be assigned to each queue making kernel aware debugging a little
+more user friendly. */
+typedef struct QUEUE_REGISTRY_ITEM {
+	signed char *pcQueueName;
+	xQueueHandle xHandle;
+} xQueueRegistryItem;
+
+/* The queue registry is simply an array of xQueueRegistryItem structures.
+The pcQueueName member of a structure being NULL is indicative of the
+array position being vacant. */
+xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
+
+/* Removes a queue from the registry by simply setting the pcQueueName
+member to NULL. */
+static void vQueueUnregisterQueue(xQueueHandle xQueue) PRIVILEGED_FUNCTION;
+void vQueueAddToRegistry(xQueueHandle xQueue, signed char *pcQueueName) PRIVILEGED_FUNCTION;
+#endif
+
+/*
+ * Unlocks a queue locked by a call to prvLockQueue.  Locking a queue does not
+ * prevent an ISR from adding or removing items to the queue, but does prevent
+ * an ISR from removing tasks from the queue event lists.  If an ISR finds a
+ * queue is locked it will instead increment the appropriate queue lock count
+ * to indicate that a task may require unblocking.  When the queue in unlocked
+ * these lock counts are inspected, and the appropriate action taken.
+ */
+static void prvUnlockQueue(xQueueHandle pxQueue) PRIVILEGED_FUNCTION;
+
+/*
+ * Uses a critical section to determine if there is any data in a queue.
+ *
+ * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
+ */
+static signed portBASE_TYPE prvIsQueueEmpty(const xQueueHandle pxQueue) PRIVILEGED_FUNCTION;
+
+/*
+ * Uses a critical section to determine if there is any space in a queue.
+ *
+ * @return pdTRUE if there is no space, otherwise pdFALSE;
+ */
+static signed portBASE_TYPE prvIsQueueFull(const xQueueHandle pxQueue) PRIVILEGED_FUNCTION;
+
+/*
+ * Copies an item into the queue, either at the front of the queue or the
+ * back of the queue.
+ */
+static void prvCopyDataToQueue(xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition) PRIVILEGED_FUNCTION;
+
+/*
+ * Copies an item out of a queue.
+ */
+static void prvCopyDataFromQueue(xQUEUE * const pxQueue, const void *pvBuffer) PRIVILEGED_FUNCTION;
+/*-----------------------------------------------------------*/
+
+/*
+ * Macro to mark a queue as locked.  Locking a queue prevents an ISR from
+ * accessing the queue event lists.
+ */
+#define prvLockQueue( pxQueue )							\
+{														\
+	taskENTER_CRITICAL();								\
+	{													\
+		if( pxQueue->xRxLock == queueUNLOCKED )			\
+		{												\
+			pxQueue->xRxLock = queueLOCKED_UNMODIFIED;	\
+		}												\
+		if( pxQueue->xTxLock == queueUNLOCKED )			\
+		{												\
+			pxQueue->xTxLock = queueLOCKED_UNMODIFIED;	\
+		}												\
+	}													\
+	taskEXIT_CRITICAL();								\
+}
+/*-----------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------
+ * PUBLIC QUEUE MANAGEMENT API documented in queue.h
+ *----------------------------------------------------------*/
+
+xQueueHandle xQueueCreate(unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize)
+{
+	xQUEUE *pxNewQueue;
+	size_t xQueueSizeInBytes;
+
+	/* Allocate the new queue structure. */
+	if (uxQueueLength > (unsigned portBASE_TYPE) 0) {
+		pxNewQueue = (xQUEUE *) pvPortMalloc(sizeof(xQUEUE));
+		if (pxNewQueue != NULL) {
+			/* Create the list of pointers to queue items.  The queue is one byte
+			longer than asked for to make wrap checking easier/faster. */
+			xQueueSizeInBytes = (size_t)(uxQueueLength * uxItemSize) + (size_t) 1;
+
+			pxNewQueue->pcHead = (signed char *) pvPortMalloc(xQueueSizeInBytes);
+			if (pxNewQueue->pcHead != NULL) {
+				/* Initialise the queue members as described above where the
+				queue type is defined. */
+				pxNewQueue->pcTail = pxNewQueue->pcHead + (uxQueueLength * uxItemSize);
+				pxNewQueue->uxMessagesWaiting = 0;
+				pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
+				pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ((uxQueueLength - 1) * uxItemSize);
+				pxNewQueue->uxLength = uxQueueLength;
+				pxNewQueue->uxItemSize = uxItemSize;
+				pxNewQueue->xRxLock = queueUNLOCKED;
+				pxNewQueue->xTxLock = queueUNLOCKED;
+
+				/* Likewise ensure the event queues start with the correct state. */
+				vListInitialise(&(pxNewQueue->xTasksWaitingToSend));
+				vListInitialise(&(pxNewQueue->xTasksWaitingToReceive));
+
+				traceQUEUE_CREATE(pxNewQueue);
+				return  pxNewQueue;
+			} else {
+				traceQUEUE_CREATE_FAILED();
+				vPortFree(pxNewQueue);
+			}
+		}
+	}
+
+	/* Will only reach here if we could not allocate enough memory or no memory
+	was required. */
+	return NULL;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+xQueueHandle xQueueCreateMutex(void)
+{
+	xQUEUE *pxNewQueue;
+
+	/* Allocate the new queue structure. */
+	pxNewQueue = (xQUEUE *) pvPortMalloc(sizeof(xQUEUE));
+	if (pxNewQueue != NULL) {
+		/* Information required for priority inheritance. */
+		pxNewQueue->pxMutexHolder = NULL;
+		pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
+
+		/* Queues used as a mutex no data is actually copied into or out
+		of the queue. */
+		pxNewQueue->pcWriteTo = NULL;
+		pxNewQueue->pcReadFrom = NULL;
+
+		/* Each mutex has a length of 1 (like a binary semaphore) and
+		an item size of 0 as nothing is actually copied into or out
+		of the mutex. */
+		pxNewQueue->uxMessagesWaiting = 0;
+		pxNewQueue->uxLength = 1;
+		pxNewQueue->uxItemSize = 0;
+		pxNewQueue->xRxLock = queueUNLOCKED;
+		pxNewQueue->xTxLock = queueUNLOCKED;
+
+		/* Ensure the event queues start with the correct state. */
+		vListInitialise(&(pxNewQueue->xTasksWaitingToSend));
+		vListInitialise(&(pxNewQueue->xTasksWaitingToReceive));
+
+		/* Start with the semaphore in the expected state. */
+		xQueueGenericSend(pxNewQueue, NULL, 0, queueSEND_TO_BACK);
+
+		traceCREATE_MUTEX(pxNewQueue);
+	} else {
+		traceCREATE_MUTEX_FAILED();
+	}
+
+	return pxNewQueue;
+}
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if configUSE_RECURSIVE_MUTEXES == 1
+
+portBASE_TYPE xQueueGiveMutexRecursive(xQueueHandle pxMutex)
+{
+	portBASE_TYPE xReturn;
+
+	/* If this is the task that holds the mutex then pxMutexHolder will not
+	change outside of this task.  If this task does not hold the mutex then
+	pxMutexHolder can never coincidentally equal the tasks handle, and as
+	this is the only condition we are interested in it does not matter if
+	pxMutexHolder is accessed simultaneously by another task.  Therefore no
+	mutual exclusion is required to test the pxMutexHolder variable. */
+	if (pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle()) {
+		traceGIVE_MUTEX_RECURSIVE(pxMutex);
+
+		/* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
+		the task handle, therefore no underflow check is required.  Also,
+		uxRecursiveCallCount is only modified by the mutex holder, and as
+		there can only be one, no mutual exclusion is required to modify the
+		uxRecursiveCallCount member. */
+		(pxMutex->uxRecursiveCallCount)--;
+
+		/* Have we unwound the call count? */
+		if (pxMutex->uxRecursiveCallCount == 0) {
+			/* Return the mutex.  This will automatically unblock any other
+			task that might be waiting to access the mutex. */
+			xQueueGenericSend(pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK);
+		}
+
+		xReturn = pdPASS;
+	} else {
+		/* We cannot give the mutex because we are not the holder. */
+		xReturn = pdFAIL;
+
+		traceGIVE_MUTEX_RECURSIVE_FAILED(pxMutex);
+	}
+
+	return xReturn;
+}
+
+#endif /* configUSE_RECURSIVE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if configUSE_RECURSIVE_MUTEXES == 1
+
+portBASE_TYPE xQueueTakeMutexRecursive(xQueueHandle pxMutex, portTickType xBlockTime)
+{
+	portBASE_TYPE xReturn;
+
+	/* Comments regarding mutual exclusion as per those within
+	xQueueGiveMutexRecursive(). */
+
+	traceTAKE_MUTEX_RECURSIVE(pxMutex);
+
+	if (pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle()) {
+		(pxMutex->uxRecursiveCallCount)++;
+		xReturn = pdPASS;
+	} else {
+		xReturn = xQueueGenericReceive(pxMutex, NULL, xBlockTime, pdFALSE);
+
+		/* pdPASS will only be returned if we successfully obtained the mutex,
+		we may have blocked to reach here. */
+		if (xReturn == pdPASS) {
+			(pxMutex->uxRecursiveCallCount)++;
+		}
+	}
+
+	return xReturn;
+}
+
+#endif /* configUSE_RECURSIVE_MUTEXES */
+/*-----------------------------------------------------------*/
+
+#if configUSE_COUNTING_SEMAPHORES == 1
+
+xQueueHandle xQueueCreateCountingSemaphore(unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount)
+{
+	xQueueHandle pxHandle;
+
+	pxHandle = xQueueCreate((unsigned portBASE_TYPE) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH);
+
+	if (pxHandle != NULL) {
+		pxHandle->uxMessagesWaiting = uxInitialCount;
+
+		traceCREATE_COUNTING_SEMAPHORE();
+	} else {
+		traceCREATE_COUNTING_SEMAPHORE_FAILED();
+	}
+
+	return pxHandle;
+}
+
+#endif /* configUSE_COUNTING_SEMAPHORES */
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueGenericSend(xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition)
+{
+	signed portBASE_TYPE xEntryTimeSet = pdFALSE;
+	xTimeOutType xTimeOut;
+
+	/* This function relaxes the coding standard somewhat to allow return
+	statements within the function itself.  This is done in the interest
+	of execution time efficiency. */
+	for (;;) {
+		taskENTER_CRITICAL();
+		{
+			/* Is there room on the queue now?  To be running we must be
+			the highest priority task wanting to access the queue. */
+			if (pxQueue->uxMessagesWaiting < pxQueue->uxLength) {
+				traceQUEUE_SEND(pxQueue);
+				prvCopyDataToQueue(pxQueue, pvItemToQueue, xCopyPosition);
+
+				/* If there was a task waiting for data to arrive on the
+				queue then unblock it now. */
+				if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE) {
+					if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) == pdTRUE) {
+						/* The unblocked task has a priority higher than
+						our own so yield immediately.  Yes it is ok to do
+						this from within the critical section - the kernel
+						takes care of that. */
+						portYIELD_WITHIN_API();
+					}
+				}
+
+				taskEXIT_CRITICAL();
+
+				/* Return to the original privilege level before exiting the
+				function. */
+				return pdPASS;
+			} else {
+				if (xTicksToWait == (portTickType) 0) {
+					/* The queue was full and no block time is specified (or
+					the block time has expired) so leave now. */
+					taskEXIT_CRITICAL();
+
+					/* Return to the original privilege level before exiting
+					the function. */
+					traceQUEUE_SEND_FAILED(pxQueue);
+					return errQUEUE_FULL;
+				} else if (xEntryTimeSet == pdFALSE) {
+					/* The queue was full and a block time was specified so
+					configure the timeout structure. */
+					vTaskSetTimeOutState(&xTimeOut);
+					xEntryTimeSet = pdTRUE;
+				}
+			}
+		}
+		taskEXIT_CRITICAL();
+
+		/* Interrupts and other tasks can send to and receive from the queue
+		now the critical section has been exited. */
+
+		vTaskSuspendAll();
+		prvLockQueue(pxQueue);
+
+		/* Update the timeout state to see if it has expired yet. */
+		if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE) {
+			if (prvIsQueueFull(pxQueue)) {
+				traceBLOCKING_ON_QUEUE_SEND(pxQueue);
+				vTaskPlaceOnEventList(&(pxQueue->xTasksWaitingToSend), xTicksToWait);
+
+				/* Unlocking the queue means queue events can effect the
+				event list.  It is possible	that interrupts occurring now
+				remove this task from the event	list again - but as the
+				scheduler is suspended the task will go onto the pending
+				ready last instead of the actual ready list. */
+				prvUnlockQueue(pxQueue);
+
+				/* Resuming the scheduler will move tasks from the pending
+				ready list into the ready list - so it is feasible that this
+				task is already in a ready list before it yields - in which
+				case the yield will not cause a context switch unless there
+				is also a higher priority task in the pending ready list. */
+				if (!xTaskResumeAll()) {
+					portYIELD_WITHIN_API();
+				}
+			} else {
+				/* Try again. */
+				prvUnlockQueue(pxQueue);
+				(void) xTaskResumeAll();
+			}
+		} else {
+			/* The timeout has expired. */
+			prvUnlockQueue(pxQueue);
+			(void) xTaskResumeAll();
+
+			/* Return to the original privilege level before exiting the
+			function. */
+			traceQUEUE_SEND_FAILED(pxQueue);
+			return errQUEUE_FULL;
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+#if configUSE_ALTERNATIVE_API == 1
+
+signed portBASE_TYPE xQueueAltGenericSend(xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition)
+{
+	signed portBASE_TYPE xEntryTimeSet = pdFALSE;
+	xTimeOutType xTimeOut;
+
+	for (;;) {
+		taskENTER_CRITICAL();
+		{
+			/* Is there room on the queue now?  To be running we must be
+			the highest priority task wanting to access the queue. */
+			if (pxQueue->uxMessagesWaiting < pxQueue->uxLength) {
+				traceQUEUE_SEND(pxQueue);
+				prvCopyDataToQueue(pxQueue, pvItemToQueue, xCopyPosition);
+
+				/* If there was a task waiting for data to arrive on the
+				queue then unblock it now. */
+				if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE) {
+					if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) == pdTRUE) {
+						/* The unblocked task has a priority higher than
+						our own so yield immediately. */
+						portYIELD_WITHIN_API();
+					}
+				}
+
+				taskEXIT_CRITICAL();
+				return pdPASS;
+			} else {
+				if (xTicksToWait == (portTickType) 0) {
+					taskEXIT_CRITICAL();
+					return errQUEUE_FULL;
+				} else if (xEntryTimeSet == pdFALSE) {
+					vTaskSetTimeOutState(&xTimeOut);
+					xEntryTimeSet = pdTRUE;
+				}
+			}
+		}
+		taskEXIT_CRITICAL();
+
+		taskENTER_CRITICAL();
+		{
+			if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE) {
+				if (prvIsQueueFull(pxQueue)) {
+					traceBLOCKING_ON_QUEUE_SEND(pxQueue);
+					vTaskPlaceOnEventList(&(pxQueue->xTasksWaitingToSend), xTicksToWait);
+					portYIELD_WITHIN_API();
+				}
+			} else {
+				taskEXIT_CRITICAL();
+				traceQUEUE_SEND_FAILED(pxQueue);
+				return errQUEUE_FULL;
+			}
+		}
+		taskEXIT_CRITICAL();
+	}
+}
+
+#endif /* configUSE_ALTERNATIVE_API */
+/*-----------------------------------------------------------*/
+
+#if configUSE_ALTERNATIVE_API == 1
+
+signed portBASE_TYPE xQueueAltGenericReceive(xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking)
+{
+	signed portBASE_TYPE xEntryTimeSet = pdFALSE;
+	xTimeOutType xTimeOut;
+	signed char *pcOriginalReadPosition;
+
+	for (;;) {
+		taskENTER_CRITICAL();
+		{
+			if (pxQueue->uxMessagesWaiting > (unsigned portBASE_TYPE) 0) {
+				/* Remember our read position in case we are just peeking. */
+				pcOriginalReadPosition = pxQueue->pcReadFrom;
+
+				prvCopyDataFromQueue(pxQueue, pvBuffer);
+
+				if (xJustPeeking == pdFALSE) {
+					traceQUEUE_RECEIVE(pxQueue);
+
+					/* We are actually removing data. */
+					--(pxQueue->uxMessagesWaiting);
+
+#if ( configUSE_MUTEXES == 1 )
+					{
+						if (pxQueue->uxQueueType == queueQUEUE_IS_MUTEX) {
+							/* Record the information required to implement
+							priority inheritance should it become necessary. */
+							pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
+						}
+					}
+#endif
+
+					if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend)) == pdFALSE) {
+						if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) == pdTRUE) {
+							portYIELD_WITHIN_API();
+						}
+					}
+				} else {
+					traceQUEUE_PEEK(pxQueue);
+
+					/* We are not removing the data, so reset our read
+					pointer. */
+					pxQueue->pcReadFrom = pcOriginalReadPosition;
+
+					/* The data is being left in the queue, so see if there are
+					any other tasks waiting for the data. */
+					if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive))) {
+						/* Tasks that are removed from the event list will get added to
+						the pending ready list as the scheduler is still suspended. */
+						if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE) {
+							/* The task waiting has a higher priority than this task. */
+							portYIELD_WITHIN_API();
+						}
+					}
+
+				}
+
+				taskEXIT_CRITICAL();
+				return pdPASS;
+			} else {
+				if (xTicksToWait == (portTickType) 0) {
+					taskEXIT_CRITICAL();
+					traceQUEUE_RECEIVE_FAILED(pxQueue);
+					return errQUEUE_EMPTY;
+				} else if (xEntryTimeSet == pdFALSE) {
+					vTaskSetTimeOutState(&xTimeOut);
+					xEntryTimeSet = pdTRUE;
+				}
+			}
+		}
+		taskEXIT_CRITICAL();
+
+		taskENTER_CRITICAL();
+		{
+			if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE) {
+				if (prvIsQueueEmpty(pxQueue)) {
+					traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue);
+
+#if ( configUSE_MUTEXES == 1 )
+					{
+						if (pxQueue->uxQueueType == queueQUEUE_IS_MUTEX) {
+							portENTER_CRITICAL();
+							vTaskPriorityInherit((void *) pxQueue->pxMutexHolder);
+							portEXIT_CRITICAL();
+						}
+					}
+#endif
+
+					vTaskPlaceOnEventList(&(pxQueue->xTasksWaitingToReceive), xTicksToWait);
+					portYIELD_WITHIN_API();
+				}
+			} else {
+				taskEXIT_CRITICAL();
+				traceQUEUE_RECEIVE_FAILED(pxQueue);
+				return errQUEUE_EMPTY;
+			}
+		}
+		taskEXIT_CRITICAL();
+	}
+}
+
+
+#endif /* configUSE_ALTERNATIVE_API */
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueGenericSendFromISR(xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition)
+{
+	signed portBASE_TYPE xReturn;
+	unsigned portBASE_TYPE uxSavedInterruptStatus;
+
+	/* Similar to xQueueGenericSend, except we don't block if there is no room
+	in the queue.  Also we don't directly wake a task that was blocked on a
+	queue read, instead we return a flag to say whether a context switch is
+	required or not (i.e. has a task with a higher priority than us been woken
+	by this	post). */
+	uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		if (pxQueue->uxMessagesWaiting < pxQueue->uxLength) {
+			traceQUEUE_SEND_FROM_ISR(pxQueue);
+
+			prvCopyDataToQueue(pxQueue, pvItemToQueue, xCopyPosition);
+
+			/* If the queue is locked we do not alter the event list.  This will
+			be done when the queue is unlocked later. */
+			if (pxQueue->xTxLock == queueUNLOCKED) {
+				if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive))) {
+					if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE) {
+						/* The task waiting has a higher priority so record that a
+						context	switch is required. */
+						*pxHigherPriorityTaskWoken = pdTRUE;
+					}
+				}
+			} else {
+				/* Increment the lock count so the task that unlocks the queue
+				knows that data was posted while it was locked. */
+				++(pxQueue->xTxLock);
+			}
+
+			xReturn = pdPASS;
+		} else {
+			traceQUEUE_SEND_FROM_ISR_FAILED(pxQueue);
+			xReturn = errQUEUE_FULL;
+		}
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueGenericReceive(xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking)
+{
+	signed portBASE_TYPE xEntryTimeSet = pdFALSE;
+	xTimeOutType xTimeOut;
+	signed char *pcOriginalReadPosition;
+
+	/* This function relaxes the coding standard somewhat to allow return
+	statements within the function itself.  This is done in the interest
+	of execution time efficiency. */
+
+	for (;;) {
+		taskENTER_CRITICAL();
+		{
+			/* Is there data in the queue now?  To be running we must be
+			the highest priority task wanting to access the queue. */
+			if (pxQueue->uxMessagesWaiting > (unsigned portBASE_TYPE) 0) {
+				/* Remember our read position in case we are just peeking. */
+				pcOriginalReadPosition = pxQueue->pcReadFrom;
+
+				prvCopyDataFromQueue(pxQueue, pvBuffer);
+
+				if (xJustPeeking == pdFALSE) {
+					traceQUEUE_RECEIVE(pxQueue);
+
+					/* We are actually removing data. */
+					--(pxQueue->uxMessagesWaiting);
+
+#if ( configUSE_MUTEXES == 1 )
+					{
+						if (pxQueue->uxQueueType == queueQUEUE_IS_MUTEX) {
+							/* Record the information required to implement
+							priority inheritance should it become necessary. */
+							pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
+						}
+					}
+#endif
+
+					if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend)) == pdFALSE) {
+						if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) == pdTRUE) {
+							portYIELD_WITHIN_API();
+						}
+					}
+				} else {
+					traceQUEUE_PEEK(pxQueue);
+
+					/* We are not removing the data, so reset our read
+					pointer. */
+					pxQueue->pcReadFrom = pcOriginalReadPosition;
+
+					/* The data is being left in the queue, so see if there are
+					any other tasks waiting for the data. */
+					if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive))) {
+						/* Tasks that are removed from the event list will get added to
+						the pending ready list as the scheduler is still suspended. */
+						if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE) {
+							/* The task waiting has a higher priority than this task. */
+							portYIELD_WITHIN_API();
+						}
+					}
+
+				}
+
+				taskEXIT_CRITICAL();
+				return pdPASS;
+			} else {
+				if (xTicksToWait == (portTickType) 0) {
+					/* The queue was empty and no block time is specified (or
+					the block time has expired) so leave now. */
+					taskEXIT_CRITICAL();
+					traceQUEUE_RECEIVE_FAILED(pxQueue);
+					return errQUEUE_EMPTY;
+				} else if (xEntryTimeSet == pdFALSE) {
+					/* The queue was empty and a block time was specified so
+					configure the timeout structure. */
+					vTaskSetTimeOutState(&xTimeOut);
+					xEntryTimeSet = pdTRUE;
+				}
+			}
+		}
+		taskEXIT_CRITICAL();
+
+		/* Interrupts and other tasks can send to and receive from the queue
+		now the critical section has been exited. */
+
+		vTaskSuspendAll();
+		prvLockQueue(pxQueue);
+
+		/* Update the timeout state to see if it has expired yet. */
+		if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE) {
+			if (prvIsQueueEmpty(pxQueue)) {
+				traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue);
+
+#if ( configUSE_MUTEXES == 1 )
+				{
+					if (pxQueue->uxQueueType == queueQUEUE_IS_MUTEX) {
+						portENTER_CRITICAL();
+						{
+							vTaskPriorityInherit((void *) pxQueue->pxMutexHolder);
+						}
+						portEXIT_CRITICAL();
+					}
+				}
+#endif
+
+				vTaskPlaceOnEventList(&(pxQueue->xTasksWaitingToReceive), xTicksToWait);
+				prvUnlockQueue(pxQueue);
+				if (!xTaskResumeAll()) {
+					portYIELD_WITHIN_API();
+				}
+			} else {
+				/* Try again. */
+				prvUnlockQueue(pxQueue);
+				(void) xTaskResumeAll();
+			}
+		} else {
+			prvUnlockQueue(pxQueue);
+			(void) xTaskResumeAll();
+			traceQUEUE_RECEIVE_FAILED(pxQueue);
+			return errQUEUE_EMPTY;
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueReceiveFromISR(xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken)
+{
+	signed portBASE_TYPE xReturn;
+	unsigned portBASE_TYPE uxSavedInterruptStatus;
+
+	uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
+	{
+		/* We cannot block from an ISR, so check there is data available. */
+		if (pxQueue->uxMessagesWaiting > (unsigned portBASE_TYPE) 0) {
+			traceQUEUE_RECEIVE_FROM_ISR(pxQueue);
+
+			prvCopyDataFromQueue(pxQueue, pvBuffer);
+			--(pxQueue->uxMessagesWaiting);
+
+			/* If the queue is locked we will not modify the event list.  Instead
+			we update the lock count so the task that unlocks the queue will know
+			that an ISR has removed data while the queue was locked. */
+			if (pxQueue->xRxLock == queueUNLOCKED) {
+				if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend))) {
+					if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE) {
+						/* The task waiting has a higher priority than us so
+						force a context switch. */
+						*pxTaskWoken = pdTRUE;
+					}
+				}
+			} else {
+				/* Increment the lock count so the task that unlocks the queue
+				knows that data was removed while it was locked. */
+				++(pxQueue->xRxLock);
+			}
+
+			xReturn = pdPASS;
+		} else {
+			xReturn = pdFAIL;
+			traceQUEUE_RECEIVE_FROM_ISR_FAILED(pxQueue);
+		}
+	}
+	portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxQueueMessagesWaiting(const xQueueHandle pxQueue)
+{
+	unsigned portBASE_TYPE uxReturn;
+
+	taskENTER_CRITICAL();
+	uxReturn = pxQueue->uxMessagesWaiting;
+	taskEXIT_CRITICAL();
+
+	return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR(const xQueueHandle pxQueue)
+{
+	unsigned portBASE_TYPE uxReturn;
+
+	uxReturn = pxQueue->uxMessagesWaiting;
+
+	return uxReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vQueueDelete(xQueueHandle pxQueue)
+{
+	traceQUEUE_DELETE(pxQueue);
+	vQueueUnregisterQueue(pxQueue);
+	vPortFree(pxQueue->pcHead);
+	vPortFree(pxQueue);
+}
+/*-----------------------------------------------------------*/
+
+static void prvCopyDataToQueue(xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition)
+{
+	if (pxQueue->uxItemSize == (unsigned portBASE_TYPE) 0) {
+#if ( configUSE_MUTEXES == 1 )
+		{
+			if (pxQueue->uxQueueType == queueQUEUE_IS_MUTEX) {
+				/* The mutex is no longer being held. */
+				vTaskPriorityDisinherit((void *) pxQueue->pxMutexHolder);
+				pxQueue->pxMutexHolder = NULL;
+			}
+		}
+#endif
+	} else if (xPosition == queueSEND_TO_BACK) {
+		memcpy((void *) pxQueue->pcWriteTo, pvItemToQueue, (unsigned) pxQueue->uxItemSize);
+		pxQueue->pcWriteTo += pxQueue->uxItemSize;
+		if (pxQueue->pcWriteTo >= pxQueue->pcTail) {
+			pxQueue->pcWriteTo = pxQueue->pcHead;
+		}
+	} else {
+		memcpy((void *) pxQueue->pcReadFrom, pvItemToQueue, (unsigned) pxQueue->uxItemSize);
+		pxQueue->pcReadFrom -= pxQueue->uxItemSize;
+		if (pxQueue->pcReadFrom < pxQueue->pcHead) {
+			pxQueue->pcReadFrom = (pxQueue->pcTail - pxQueue->uxItemSize);
+		}
+	}
+
+	++(pxQueue->uxMessagesWaiting);
+}
+/*-----------------------------------------------------------*/
+
+static void prvCopyDataFromQueue(xQUEUE * const pxQueue, const void *pvBuffer)
+{
+	if (pxQueue->uxQueueType != queueQUEUE_IS_MUTEX) {
+		pxQueue->pcReadFrom += pxQueue->uxItemSize;
+		if (pxQueue->pcReadFrom >= pxQueue->pcTail) {
+			pxQueue->pcReadFrom = pxQueue->pcHead;
+		}
+		memcpy((void *) pvBuffer, (void *) pxQueue->pcReadFrom, (unsigned) pxQueue->uxItemSize);
+	}
+}
+/*-----------------------------------------------------------*/
+
+static void prvUnlockQueue(xQueueHandle pxQueue)
+{
+	/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
+
+	/* The lock counts contains the number of extra data items placed or
+	removed from the queue while the queue was locked.  When a queue is
+	locked items can be added or removed, but the event lists cannot be
+	updated. */
+	taskENTER_CRITICAL();
+	{
+		/* See if data was added to the queue while it was locked. */
+		while (pxQueue->xTxLock > queueLOCKED_UNMODIFIED) {
+			/* Data was posted while the queue was locked.  Are any tasks
+			blocked waiting for data to become available? */
+			if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive))) {
+				/* Tasks that are removed from the event list will get added to
+				the pending ready list as the scheduler is still suspended. */
+				if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE) {
+					/* The task waiting has a higher priority so record that a
+					context	switch is required. */
+					vTaskMissedYield();
+				}
+
+				--(pxQueue->xTxLock);
+			} else {
+				break;
+			}
+		}
+
+		pxQueue->xTxLock = queueUNLOCKED;
+	}
+	taskEXIT_CRITICAL();
+
+	/* Do the same for the Rx lock. */
+	taskENTER_CRITICAL();
+	{
+		while (pxQueue->xRxLock > queueLOCKED_UNMODIFIED) {
+			if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend))) {
+				if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE) {
+					vTaskMissedYield();
+				}
+
+				--(pxQueue->xRxLock);
+			} else {
+				break;
+			}
+		}
+
+		pxQueue->xRxLock = queueUNLOCKED;
+	}
+	taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+static signed portBASE_TYPE prvIsQueueEmpty(const xQueueHandle pxQueue)
+{
+	signed portBASE_TYPE xReturn;
+
+	taskENTER_CRITICAL();
+	xReturn = (pxQueue->uxMessagesWaiting == (unsigned portBASE_TYPE) 0);
+	taskEXIT_CRITICAL();
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueIsQueueEmptyFromISR(const xQueueHandle pxQueue)
+{
+	signed portBASE_TYPE xReturn;
+
+	xReturn = (pxQueue->uxMessagesWaiting == (unsigned portBASE_TYPE) 0);
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+static signed portBASE_TYPE prvIsQueueFull(const xQueueHandle pxQueue)
+{
+	signed portBASE_TYPE xReturn;
+
+	taskENTER_CRITICAL();
+	xReturn = (pxQueue->uxMessagesWaiting == pxQueue->uxLength);
+	taskEXIT_CRITICAL();
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xQueueIsQueueFullFromISR(const xQueueHandle pxQueue)
+{
+	signed portBASE_TYPE xReturn;
+
+	xReturn = (pxQueue->uxMessagesWaiting == pxQueue->uxLength);
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if configUSE_CO_ROUTINES == 1
+signed portBASE_TYPE xQueueCRSend(xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait)
+{
+	signed portBASE_TYPE xReturn;
+
+	/* If the queue is already full we may have to block.  A critical section
+	is required to prevent an interrupt removing something from the queue
+	between the check to see if the queue is full and blocking on the queue. */
+	portDISABLE_INTERRUPTS();
+	{
+		if (prvIsQueueFull(pxQueue)) {
+			/* The queue is full - do we want to block or just leave without
+			posting? */
+			if (xTicksToWait > (portTickType) 0) {
+				/* As this is called from a coroutine we cannot block directly, but
+				return indicating that we need to block. */
+				vCoRoutineAddToDelayedList(xTicksToWait, &(pxQueue->xTasksWaitingToSend));
+				portENABLE_INTERRUPTS();
+				return errQUEUE_BLOCKED;
+			} else {
+				portENABLE_INTERRUPTS();
+				return errQUEUE_FULL;
+			}
+		}
+	}
+	portENABLE_INTERRUPTS();
+
+	portNOP();
+
+	portDISABLE_INTERRUPTS();
+	{
+		if (pxQueue->uxMessagesWaiting < pxQueue->uxLength) {
+			/* There is room in the queue, copy the data into the queue. */
+			prvCopyDataToQueue(pxQueue, pvItemToQueue, queueSEND_TO_BACK);
+			xReturn = pdPASS;
+
+			/* Were any co-routines waiting for data to become available? */
+			if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive))) {
+				/* In this instance the co-routine could be placed directly
+				into the ready list as we are within a critical section.
+				Instead the same pending ready list mechanism is used as if
+				the event were caused from within an interrupt. */
+				if (xCoRoutineRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE) {
+					/* The co-routine waiting has a higher priority so record
+					that a yield might be appropriate. */
+					xReturn = errQUEUE_YIELD;
+				}
+			}
+		} else {
+			xReturn = errQUEUE_FULL;
+		}
+	}
+	portENABLE_INTERRUPTS();
+
+	return xReturn;
+}
+#endif
+/*-----------------------------------------------------------*/
+
+#if configUSE_CO_ROUTINES == 1
+signed portBASE_TYPE xQueueCRReceive(xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait)
+{
+	signed portBASE_TYPE xReturn;
+
+	/* If the queue is already empty we may have to block.  A critical section
+	is required to prevent an interrupt adding something to the queue
+	between the check to see if the queue is empty and blocking on the queue. */
+	portDISABLE_INTERRUPTS();
+	{
+		if (pxQueue->uxMessagesWaiting == (unsigned portBASE_TYPE) 0) {
+			/* There are no messages in the queue, do we want to block or just
+			leave with nothing? */
+			if (xTicksToWait > (portTickType) 0) {
+				/* As this is a co-routine we cannot block directly, but return
+				indicating that we need to block. */
+				vCoRoutineAddToDelayedList(xTicksToWait, &(pxQueue->xTasksWaitingToReceive));
+				portENABLE_INTERRUPTS();
+				return errQUEUE_BLOCKED;
+			} else {
+				portENABLE_INTERRUPTS();
+				return errQUEUE_FULL;
+			}
+		}
+	}
+	portENABLE_INTERRUPTS();
+
+	portNOP();
+
+	portDISABLE_INTERRUPTS();
+	{
+		if (pxQueue->uxMessagesWaiting > (unsigned portBASE_TYPE) 0) {
+			/* Data is available from the queue. */
+			pxQueue->pcReadFrom += pxQueue->uxItemSize;
+			if (pxQueue->pcReadFrom >= pxQueue->pcTail) {
+				pxQueue->pcReadFrom = pxQueue->pcHead;
+			}
+			--(pxQueue->uxMessagesWaiting);
+			memcpy((void *) pvBuffer, (void *) pxQueue->pcReadFrom, (unsigned) pxQueue->uxItemSize);
+
+			xReturn = pdPASS;
+
+			/* Were any co-routines waiting for space to become available? */
+			if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend))) {
+				/* In this instance the co-routine could be placed directly
+				into the ready list as we are within a critical section.
+				Instead the same pending ready list mechanism is used as if
+				the event were caused from within an interrupt. */
+				if (xCoRoutineRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE) {
+					xReturn = errQUEUE_YIELD;
+				}
+			}
+		} else {
+			xReturn = pdFAIL;
+		}
+	}
+	portENABLE_INTERRUPTS();
+
+	return xReturn;
+}
+#endif
+/*-----------------------------------------------------------*/
+
+
+
+#if configUSE_CO_ROUTINES == 1
+signed portBASE_TYPE xQueueCRSendFromISR(xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken)
+{
+	/* Cannot block within an ISR so if there is no space on the queue then
+	exit without doing anything. */
+	if (pxQueue->uxMessagesWaiting < pxQueue->uxLength) {
+		prvCopyDataToQueue(pxQueue, pvItemToQueue, queueSEND_TO_BACK);
+
+		/* We only want to wake one co-routine per ISR, so check that a
+		co-routine has not already been woken. */
+		if (!xCoRoutinePreviouslyWoken) {
+			if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive))) {
+				if (xCoRoutineRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE) {
+					return pdTRUE;
+				}
+			}
+		}
+	}
+
+	return xCoRoutinePreviouslyWoken;
+}
+#endif
+/*-----------------------------------------------------------*/
+
+#if configUSE_CO_ROUTINES == 1
+signed portBASE_TYPE xQueueCRReceiveFromISR(xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken)
+{
+	signed portBASE_TYPE xReturn;
+
+	/* We cannot block from an ISR, so check there is data available. If
+	not then just leave without doing anything. */
+	if (pxQueue->uxMessagesWaiting > (unsigned portBASE_TYPE) 0) {
+		/* Copy the data from the queue. */
+		pxQueue->pcReadFrom += pxQueue->uxItemSize;
+		if (pxQueue->pcReadFrom >= pxQueue->pcTail) {
+			pxQueue->pcReadFrom = pxQueue->pcHead;
+		}
+		--(pxQueue->uxMessagesWaiting);
+		memcpy((void *) pvBuffer, (void *) pxQueue->pcReadFrom, (unsigned) pxQueue->uxItemSize);
+
+		if (!(*pxCoRoutineWoken)) {
+			if (!listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend))) {
+				if (xCoRoutineRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE) {
+					*pxCoRoutineWoken = pdTRUE;
+				}
+			}
+		}
+
+		xReturn = pdPASS;
+	} else {
+		xReturn = pdFAIL;
+	}
+
+	return xReturn;
+}
+#endif
+/*-----------------------------------------------------------*/
+
+#if configQUEUE_REGISTRY_SIZE > 0
+
+void vQueueAddToRegistry(xQueueHandle xQueue, signed char *pcQueueName)
+{
+	unsigned portBASE_TYPE ux;
+
+	/* See if there is an empty space in the registry.  A NULL name denotes
+	a free slot. */
+	for (ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++) {
+		if (xQueueRegistry[ ux ].pcQueueName == NULL) {
+			/* Store the information on this queue. */
+			xQueueRegistry[ ux ].pcQueueName = pcQueueName;
+			xQueueRegistry[ ux ].xHandle = xQueue;
+			break;
+		}
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if configQUEUE_REGISTRY_SIZE > 0
+
+static void vQueueUnregisterQueue(xQueueHandle xQueue)
+{
+	unsigned portBASE_TYPE ux;
+
+	/* See if the handle of the queue being unregistered in actually in the
+	registry. */
+	for (ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++) {
+		if (xQueueRegistry[ ux ].xHandle == xQueue) {
+			/* Set the name to NULL to show that this slot if free again. */
+			xQueueRegistry[ ux ].pcQueueName = NULL;
+			break;
+		}
+	}
+
+}
+
+#endif
+
diff --git a/gyro_board/src/usb/FreeRTOS/tasks.c b/gyro_board/src/usb/FreeRTOS/tasks.c
new file mode 100644
index 0000000..22587a4
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOS/tasks.c
@@ -0,0 +1,2150 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
+all the API functions to use the MPU wrappers.  That should only be done when
+task.h is included from an application file. */
+#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "StackMacros.h"
+
+#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
+
+/*
+ * Macro to define the amount of stack available to the idle task.
+ */
+#define tskIDLE_STACK_SIZE	configMINIMAL_STACK_SIZE
+
+/*
+ * Task control block.  A task control block (TCB) is allocated to each task,
+ * and stores the context of the task.
+ */
+typedef struct tskTaskControlBlock {
+	volatile portSTACK_TYPE	*pxTopOfStack;		/*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */
+
+#if ( portUSING_MPU_WRAPPERS == 1 )
+	xMPU_SETTINGS xMPUSettings;				/*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */
+#endif
+
+	xListItem				xGenericListItem;	/*< List item used to place the TCB in ready and blocked queues. */
+	xListItem				xEventListItem;		/*< List item used to place the TCB in event lists. */
+	unsigned portBASE_TYPE	uxPriority;			/*< The priority of the task where 0 is the lowest priority. */
+	portSTACK_TYPE			*pxStack;			/*< Points to the start of the stack. */
+	signed char				pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */
+
+#if ( portSTACK_GROWTH > 0 )
+	portSTACK_TYPE *pxEndOfStack;			/*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
+#endif
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+	unsigned portBASE_TYPE uxCriticalNesting;
+#endif
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+	unsigned portBASE_TYPE	uxTCBNumber;	/*< This is used for tracing the scheduler and making debugging easier only. */
+#endif
+
+#if ( configUSE_MUTEXES == 1 )
+	unsigned portBASE_TYPE uxBasePriority;	/*< The priority last assigned to the task - used by the priority inheritance mechanism. */
+#endif
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+	pdTASK_HOOK_CODE pxTaskTag;
+#endif
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+	unsigned long ulRunTimeCounter;		/*< Used for calculating how much CPU time each task is utilising. */
+#endif
+
+} tskTCB;
+
+
+/*
+ * Some kernel aware debuggers require data to be viewed to be global, rather
+ * than file scope.
+ */
+#ifdef portREMOVE_STATIC_QUALIFIER
+#define static
+#endif
+
+/*lint -e956 */
+PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
+
+/* Lists for ready and blocked tasks. --------------------*/
+
+PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ];	/*< Prioritised ready tasks. */
+PRIVILEGED_DATA static xList xDelayedTaskList1;							/*< Delayed tasks. */
+PRIVILEGED_DATA static xList xDelayedTaskList2;							/*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
+PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ;				/*< Points to the delayed task list currently being used. */
+PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList;		/*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
+PRIVILEGED_DATA static xList xPendingReadyList;							/*< Tasks that have been readied while the scheduler was suspended.  They will be moved to the ready queue when the scheduler is resumed. */
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+PRIVILEGED_DATA static volatile xList xTasksWaitingTermination;		/*< Tasks that have been deleted - but the their memory not yet freed. */
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = (unsigned portBASE_TYPE) 0;
+
+#endif
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+PRIVILEGED_DATA static xList xSuspendedTaskList;					/*< Tasks that are currently suspended. */
+
+#endif
+
+/* File private variables. --------------------------------*/
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks 	= (unsigned portBASE_TYPE) 0;
+PRIVILEGED_DATA static volatile portTickType xTickCount 						= (portTickType) 0;
+PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority	 				= tskIDLE_PRIORITY;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority 		= tskIDLE_PRIORITY;
+PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning 			= pdFALSE;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended	 	= (unsigned portBASE_TYPE) pdFALSE;
+PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks 			= (unsigned portBASE_TYPE) 0;
+PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield 						= (portBASE_TYPE) pdFALSE;
+PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows 					= (portBASE_TYPE) 0;
+PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber 						= (unsigned portBASE_TYPE) 0;
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+PRIVILEGED_DATA static char pcStatsString[ 50 ] ;
+PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL;	/*< Holds the value of a timer/counter the last time a task was switched in. */
+static void prvGenerateRunTimeStatsForTasksInList(const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime) PRIVILEGED_FUNCTION;
+
+#endif
+
+/* Debugging and trace facilities private variables and macros. ------------*/
+
+/*
+ * The value used to fill the stack of a task when the task is created.  This
+ * is used purely for checking the high water mark for tasks.
+ */
+#define tskSTACK_FILL_BYTE	( 0xa5 )
+
+/*
+ * Macros used by vListTask to indicate which state a task is in.
+ */
+#define tskBLOCKED_CHAR		( ( signed char ) 'B' )
+#define tskREADY_CHAR		( ( signed char ) 'R' )
+#define tskDELETED_CHAR		( ( signed char ) 'D' )
+#define tskSUSPENDED_CHAR	( ( signed char ) 'S' )
+
+/*
+ * Macros and private variables used by the trace facility.
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+#define tskSIZE_OF_EACH_TRACE_LINE			( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) )
+PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer;
+PRIVILEGED_DATA static signed char *pcTraceBufferStart;
+PRIVILEGED_DATA static signed char *pcTraceBufferEnd;
+PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE;
+static unsigned portBASE_TYPE uxPreviousTask = 255;
+PRIVILEGED_DATA static char pcStatusString[ 50 ];
+
+#endif
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Macro that writes a trace of scheduler activity to a buffer.  This trace
+ * shows which task is running when and is very useful as a debugging tool.
+ * As this macro is called each context switch it is a good idea to undefine
+ * it if not using the facility.
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+#define vWriteTraceToBuffer()																	\
+	{																								\
+		if( xTracing )																				\
+		{																							\
+			if( uxPreviousTask != pxCurrentTCB->uxTCBNumber )										\
+			{																						\
+				if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd )				\
+				{																					\
+					uxPreviousTask = pxCurrentTCB->uxTCBNumber;										\
+					*( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount;		\
+					pcTraceBuffer += sizeof( unsigned long );									\
+					*( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask;	\
+					pcTraceBuffer += sizeof( unsigned long );									\
+				}																					\
+				else																				\
+				{																					\
+					xTracing = pdFALSE;																\
+				}																					\
+			}																						\
+		}																							\
+	}
+
+#else
+
+#define vWriteTraceToBuffer()
+
+#endif
+/*-----------------------------------------------------------*/
+
+/*
+ * Place the task represented by pxTCB into the appropriate ready queue for
+ * the task.  It is inserted at the end of the list.  One quirk of this is
+ * that if the task being inserted is at the same priority as the currently
+ * executing task, then it will only be rescheduled after the currently
+ * executing task has been rescheduled.
+ */
+#define prvAddTaskToReadyQueue( pxTCB )																			\
+{																												\
+	if( pxTCB->uxPriority > uxTopReadyPriority )																\
+	{																											\
+		uxTopReadyPriority = pxTCB->uxPriority;																	\
+	}																											\
+	vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) );	\
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Macro that looks at the list of tasks that are currently delayed to see if
+ * any require waking.
+ *
+ * Tasks are stored in the queue in the order of their wake time - meaning
+ * once one tasks has been found whose timer has not expired we need not look
+ * any further down the list.
+ */
+#define prvCheckDelayedTasks()																						\
+{																													\
+register tskTCB *pxTCB;																								\
+																													\
+	while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL )						\
+	{																												\
+		if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) )									\
+		{																											\
+			break;																									\
+		}																											\
+		vListRemove( &( pxTCB->xGenericListItem ) );																\
+		/* Is the task waiting on an event also? */																	\
+		if( pxTCB->xEventListItem.pvContainer )																		\
+		{																											\
+			vListRemove( &( pxTCB->xEventListItem ) );																\
+		}																											\
+		prvAddTaskToReadyQueue( pxTCB );																			\
+	}																												\
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Several functions take an xTaskHandle parameter that can optionally be NULL,
+ * where NULL is used to indicate that the handle of the currently executing
+ * task should be used in place of the parameter.  This macro simply checks to
+ * see if the parameter is NULL and returns a pointer to the appropriate TCB.
+ */
+#define prvGetTCBFromHandle( pxHandle ) ( ( pxHandle == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) pxHandle )
+
+
+/* File private functions. --------------------------------*/
+
+/*
+ * Utility to ready a TCB for a given task.  Mainly just copies the parameters
+ * into the TCB structure.
+ */
+static void prvInitialiseTCBVariables(tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth) PRIVILEGED_FUNCTION;
+
+/*
+ * Utility to ready all the lists used by the scheduler.  This is called
+ * automatically upon the creation of the first task.
+ */
+static void prvInitialiseTaskLists(void) PRIVILEGED_FUNCTION;
+
+/*
+ * The idle task, which as all tasks is implemented as a never ending loop.
+ * The idle task is automatically created and added to the ready lists upon
+ * creation of the first user task.
+ *
+ * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
+ * language extensions.  The equivalent prototype for this function is:
+ *
+ * void prvIdleTask( void *pvParameters );
+ *
+ */
+static portTASK_FUNCTION_PROTO(prvIdleTask, pvParameters);
+
+/*
+ * Utility to free all memory allocated by the scheduler to hold a TCB,
+ * including the stack pointed to by the TCB.
+ *
+ * This does not free memory allocated by the task itself (i.e. memory
+ * allocated by calls to pvPortMalloc from within the tasks application code).
+ */
+#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
+
+static void prvDeleteTCB(tskTCB *pxTCB) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * Used only by the idle task.  This checks to see if anything has been placed
+ * in the list of tasks waiting to be deleted.  If so the task is cleaned up
+ * and its TCB deleted.
+ */
+static void prvCheckTasksWaitingTermination(void) PRIVILEGED_FUNCTION;
+
+/*
+ * Allocates memory from the heap for a TCB and associated stack.  Checks the
+ * allocation was successful.
+ */
+static tskTCB *prvAllocateTCBAndStack(unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer) PRIVILEGED_FUNCTION;
+
+/*
+ * Called from vTaskList.  vListTasks details all the tasks currently under
+ * control of the scheduler.  The tasks may be in one of a number of lists.
+ * prvListTaskWithinSingleList accepts a list and details the tasks from
+ * within just that list.
+ *
+ * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
+ * NORMAL APPLICATION CODE.
+ */
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+static void prvListTaskWithinSingleList(const signed char *pcWriteBuffer, xList *pxList, signed char cStatus) PRIVILEGED_FUNCTION;
+
+#endif
+
+/*
+ * When a task is created, the stack of the task is filled with a known value.
+ * This function determines the 'high water mark' of the task stack by
+ * determining how much of the stack remains at the original preset value.
+ */
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+
+static unsigned short usTaskCheckFreeStackSpace(const unsigned char * pucStackByte) PRIVILEGED_FUNCTION;
+
+#endif
+
+
+/*lint +e956 */
+
+
+
+/*-----------------------------------------------------------
+ * TASK CREATION API documented in task.h
+ *----------------------------------------------------------*/
+
+signed portBASE_TYPE xTaskGenericCreate(pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions)
+{
+	signed portBASE_TYPE xReturn;
+	tskTCB * pxNewTCB;
+
+	/* Allocate the memory required by the TCB and stack for the new task,
+	checking that the allocation was successful. */
+	pxNewTCB = prvAllocateTCBAndStack(usStackDepth, puxStackBuffer);
+
+	if (pxNewTCB != NULL) {
+		portSTACK_TYPE *pxTopOfStack;
+
+#if( portUSING_MPU_WRAPPERS == 1 )
+		/* Should the task be created in privileged mode? */
+		portBASE_TYPE xRunPrivileged;
+		if ((uxPriority & portPRIVILEGE_BIT) != 0x00) {
+			xRunPrivileged = pdTRUE;
+		} else {
+			xRunPrivileged = pdFALSE;
+		}
+		uxPriority &= ~portPRIVILEGE_BIT;
+#endif /* portUSING_MPU_WRAPPERS == 1 */
+
+		/* Calculate the top of stack address.  This depends on whether the
+		stack grows from high memory to low (as per the 80x86) or visa versa.
+		portSTACK_GROWTH is used to make the result positive or negative as
+		required by the port. */
+#if( portSTACK_GROWTH < 0 )
+		{
+			pxTopOfStack = pxNewTCB->pxStack + (usStackDepth - 1);
+			pxTopOfStack = (portSTACK_TYPE *)(((unsigned long) pxTopOfStack) & ((unsigned long) ~portBYTE_ALIGNMENT_MASK));
+		}
+#else
+		{
+			pxTopOfStack = pxNewTCB->pxStack;
+
+			/* If we want to use stack checking on architectures that use
+			a positive stack growth direction then we also need to store the
+			other extreme of the stack space. */
+			pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + (usStackDepth - 1);
+		}
+#endif
+
+		/* Setup the newly allocated TCB with the initial state of the task. */
+		prvInitialiseTCBVariables(pxNewTCB, pcName, uxPriority, xRegions, usStackDepth);
+
+		/* Initialize the TCB stack to look as if the task was already running,
+		but had been interrupted by the scheduler.  The return address is set
+		to the start of the task function. Once the stack has been initialised
+		the	top of stack variable is updated. */
+#if( portUSING_MPU_WRAPPERS == 1 )
+		{
+			pxNewTCB->pxTopOfStack = pxPortInitialiseStack(pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged);
+		}
+#else
+		{
+			pxNewTCB->pxTopOfStack = pxPortInitialiseStack(pxTopOfStack, pxTaskCode, pvParameters);
+		}
+#endif
+
+		/* We are going to manipulate the task queues to add this task to a
+		ready list, so must make sure no interrupts occur. */
+		portENTER_CRITICAL();
+		{
+			uxCurrentNumberOfTasks++;
+			if (uxCurrentNumberOfTasks == (unsigned portBASE_TYPE) 1) {
+				/* As this is the first task it must also be the current task. */
+				pxCurrentTCB =  pxNewTCB;
+
+				/* This is the first task to be created so do the preliminary
+				initialisation required.  We will not recover if this call
+				fails, but we will report the failure. */
+				prvInitialiseTaskLists();
+			} else {
+				/* If the scheduler is not already running, make this task the
+				current task if it is the highest priority task to be created
+				so far. */
+				if (xSchedulerRunning == pdFALSE) {
+					if (pxCurrentTCB->uxPriority <= uxPriority) {
+						pxCurrentTCB = pxNewTCB;
+					}
+				}
+			}
+
+			/* Remember the top priority to make context switching faster.  Use
+			the priority in pxNewTCB as this has been capped to a valid value. */
+			if (pxNewTCB->uxPriority > uxTopUsedPriority) {
+				uxTopUsedPriority = pxNewTCB->uxPriority;
+			}
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+			{
+				/* Add a counter into the TCB for tracing only. */
+				pxNewTCB->uxTCBNumber = uxTaskNumber;
+			}
+#endif
+			uxTaskNumber++;
+
+			prvAddTaskToReadyQueue(pxNewTCB);
+
+			xReturn = pdPASS;
+			traceTASK_CREATE(pxNewTCB);
+		}
+		portEXIT_CRITICAL();
+	} else {
+		xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+		traceTASK_CREATE_FAILED(pxNewTCB);
+	}
+
+	if (xReturn == pdPASS) {
+		if ((void *) pxCreatedTask != NULL) {
+			/* Pass the TCB out - in an anonymous way.  The calling function/
+			task can use this as a handle to delete the task later if
+			required.*/
+			*pxCreatedTask = (xTaskHandle) pxNewTCB;
+		}
+
+		if (xSchedulerRunning != pdFALSE) {
+			/* If the created task is of a higher priority than the current task
+			then it should run now. */
+			if (pxCurrentTCB->uxPriority < uxPriority) {
+				portYIELD_WITHIN_API();
+			}
+		}
+	}
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelete == 1 )
+
+void vTaskDelete(xTaskHandle pxTaskToDelete)
+{
+	tskTCB *pxTCB;
+
+	portENTER_CRITICAL();
+	{
+		/* Ensure a yield is performed if the current task is being
+		deleted. */
+		if (pxTaskToDelete == pxCurrentTCB) {
+			pxTaskToDelete = NULL;
+		}
+
+		/* If null is passed in here then we are deleting ourselves. */
+		pxTCB = prvGetTCBFromHandle(pxTaskToDelete);
+
+		/* Remove task from the ready list and place in the	termination list.
+		This will stop the task from be scheduled.  The idle task will check
+		the termination list and free up any memory allocated by the
+		scheduler for the TCB and stack. */
+		vListRemove(&(pxTCB->xGenericListItem));
+
+		/* Is the task waiting on an event also? */
+		if (pxTCB->xEventListItem.pvContainer) {
+			vListRemove(&(pxTCB->xEventListItem));
+		}
+
+		vListInsertEnd((xList *) &xTasksWaitingTermination, &(pxTCB->xGenericListItem));
+
+		/* Increment the ucTasksDeleted variable so the idle task knows
+		there is a task that has been deleted and that it should therefore
+		check the xTasksWaitingTermination list. */
+		++uxTasksDeleted;
+
+		/* Increment the uxTaskNumberVariable also so kernel aware debuggers
+		can detect that the task lists need re-generating. */
+		uxTaskNumber++;
+
+		traceTASK_DELETE(pxTCB);
+	}
+	portEXIT_CRITICAL();
+
+	/* Force a reschedule if we have just deleted the current task. */
+	if (xSchedulerRunning != pdFALSE) {
+		if ((void *) pxTaskToDelete == NULL) {
+			portYIELD_WITHIN_API();
+		}
+	}
+}
+
+#endif
+
+
+
+
+
+
+/*-----------------------------------------------------------
+ * TASK CONTROL API documented in task.h
+ *----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelayUntil == 1 )
+
+void vTaskDelayUntil(portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement)
+{
+	portTickType xTimeToWake;
+	portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
+
+	vTaskSuspendAll();
+	{
+		/* Generate the tick time at which the task wants to wake. */
+		xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
+
+		if (xTickCount < *pxPreviousWakeTime) {
+			/* The tick count has overflowed since this function was
+			lasted called.  In this case the only time we should ever
+			actually delay is if the wake time has also	overflowed,
+			and the wake time is greater than the tick time.  When this
+			is the case it is as if neither time had overflowed. */
+			if ((xTimeToWake < *pxPreviousWakeTime) && (xTimeToWake > xTickCount)) {
+				xShouldDelay = pdTRUE;
+			}
+		} else {
+			/* The tick time has not overflowed.  In this case we will
+			delay if either the wake time has overflowed, and/or the
+			tick time is less than the wake time. */
+			if ((xTimeToWake < *pxPreviousWakeTime) || (xTimeToWake > xTickCount)) {
+				xShouldDelay = pdTRUE;
+			}
+		}
+
+		/* Update the wake time ready for the next call. */
+		*pxPreviousWakeTime = xTimeToWake;
+
+		if (xShouldDelay) {
+			traceTASK_DELAY_UNTIL();
+
+			/* We must remove ourselves from the ready list before adding
+			ourselves to the blocked list as the same list item is used for
+			both lists. */
+			vListRemove((xListItem *) &(pxCurrentTCB->xGenericListItem));
+
+			/* The list item will be inserted in wake time order. */
+			listSET_LIST_ITEM_VALUE(&(pxCurrentTCB->xGenericListItem), xTimeToWake);
+
+			if (xTimeToWake < xTickCount) {
+				/* Wake time has overflowed.  Place this item in the
+				overflow list. */
+				vListInsert((xList *) pxOverflowDelayedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+			} else {
+				/* The wake time has not overflowed, so we can use the
+				current block list. */
+				vListInsert((xList *) pxDelayedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+			}
+		}
+	}
+	xAlreadyYielded = xTaskResumeAll();
+
+	/* Force a reschedule if xTaskResumeAll has not already done so, we may
+	have put ourselves to sleep. */
+	if (!xAlreadyYielded) {
+		portYIELD_WITHIN_API();
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskDelay == 1 )
+
+void vTaskDelay(portTickType xTicksToDelay)
+{
+	portTickType xTimeToWake;
+	signed portBASE_TYPE xAlreadyYielded = pdFALSE;
+
+	/* A delay time of zero just forces a reschedule. */
+	if (xTicksToDelay > (portTickType) 0) {
+		vTaskSuspendAll();
+		{
+			traceTASK_DELAY();
+
+			/* A task that is removed from the event list while the
+			scheduler is suspended will not get placed in the ready
+			list or removed from the blocked list until the scheduler
+			is resumed.
+
+			This task cannot be in an event list as it is the currently
+			executing task. */
+
+			/* Calculate the time to wake - this may overflow but this is
+			not a problem. */
+			xTimeToWake = xTickCount + xTicksToDelay;
+
+			/* We must remove ourselves from the ready list before adding
+			ourselves to the blocked list as the same list item is used for
+			both lists. */
+			vListRemove((xListItem *) &(pxCurrentTCB->xGenericListItem));
+
+			/* The list item will be inserted in wake time order. */
+			listSET_LIST_ITEM_VALUE(&(pxCurrentTCB->xGenericListItem), xTimeToWake);
+
+			if (xTimeToWake < xTickCount) {
+				/* Wake time has overflowed.  Place this item in the
+				overflow list. */
+				vListInsert((xList *) pxOverflowDelayedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+			} else {
+				/* The wake time has not overflowed, so we can use the
+				current block list. */
+				vListInsert((xList *) pxDelayedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+			}
+		}
+		xAlreadyYielded = xTaskResumeAll();
+	}
+
+	/* Force a reschedule if xTaskResumeAll has not already done so, we may
+	have put ourselves to sleep. */
+	if (!xAlreadyYielded) {
+		portYIELD_WITHIN_API();
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskPriorityGet == 1 )
+
+unsigned portBASE_TYPE uxTaskPriorityGet(xTaskHandle pxTask)
+{
+	tskTCB *pxTCB;
+	unsigned portBASE_TYPE uxReturn;
+
+	portENTER_CRITICAL();
+	{
+		/* If null is passed in here then we are changing the
+		priority of the calling function. */
+		pxTCB = prvGetTCBFromHandle(pxTask);
+		uxReturn = pxTCB->uxPriority;
+	}
+	portEXIT_CRITICAL();
+
+	return uxReturn;
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskPrioritySet == 1 )
+
+void vTaskPrioritySet(xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority)
+{
+	tskTCB *pxTCB;
+	unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE;
+
+	/* Ensure the new priority is valid. */
+	if (uxNewPriority >= configMAX_PRIORITIES) {
+		uxNewPriority = configMAX_PRIORITIES - 1;
+	}
+
+	portENTER_CRITICAL();
+	{
+		if (pxTask == pxCurrentTCB) {
+			pxTask = NULL;
+		}
+
+		/* If null is passed in here then we are changing the
+		priority of the calling function. */
+		pxTCB = prvGetTCBFromHandle(pxTask);
+
+		traceTASK_PRIORITY_SET(pxTask, uxNewPriority);
+
+#if ( configUSE_MUTEXES == 1 )
+		{
+			uxCurrentPriority = pxTCB->uxBasePriority;
+		}
+#else
+		{
+			uxCurrentPriority = pxTCB->uxPriority;
+		}
+#endif
+
+		if (uxCurrentPriority != uxNewPriority) {
+			/* The priority change may have readied a task of higher
+			priority than the calling task. */
+			if (uxNewPriority > uxCurrentPriority) {
+				if (pxTask != NULL) {
+					/* The priority of another task is being raised.  If we
+					were raising the priority of the currently running task
+					there would be no need to switch as it must have already
+					been the highest priority task. */
+					xYieldRequired = pdTRUE;
+				}
+			} else if (pxTask == NULL) {
+				/* Setting our own priority down means there may now be another
+				task of higher priority that is ready to execute. */
+				xYieldRequired = pdTRUE;
+			}
+
+
+
+#if ( configUSE_MUTEXES == 1 )
+			{
+				/* Only change the priority being used if the task is not
+				currently using an inherited priority. */
+				if (pxTCB->uxBasePriority == pxTCB->uxPriority) {
+					pxTCB->uxPriority = uxNewPriority;
+				}
+
+				/* The base priority gets set whatever. */
+				pxTCB->uxBasePriority = uxNewPriority;
+			}
+#else
+			{
+				pxTCB->uxPriority = uxNewPriority;
+			}
+#endif
+
+			listSET_LIST_ITEM_VALUE(&(pxTCB->xEventListItem), (configMAX_PRIORITIES - (portTickType) uxNewPriority));
+
+			/* If the task is in the blocked or suspended list we need do
+			nothing more than change it's priority variable. However, if
+			the task is in a ready list it needs to be removed and placed
+			in the queue appropriate to its new priority. */
+			if (listIS_CONTAINED_WITHIN(&(pxReadyTasksLists[ uxCurrentPriority ]), &(pxTCB->xGenericListItem))) {
+				/* The task is currently in its ready list - remove before adding
+				it to it's new ready list.  As we are in a critical section we
+				can do this even if the scheduler is suspended. */
+				vListRemove(&(pxTCB->xGenericListItem));
+				prvAddTaskToReadyQueue(pxTCB);
+			}
+
+			if (xYieldRequired == pdTRUE) {
+				portYIELD_WITHIN_API();
+			}
+		}
+	}
+	portEXIT_CRITICAL();
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+void vTaskSuspend(xTaskHandle pxTaskToSuspend)
+{
+	tskTCB *pxTCB;
+
+	portENTER_CRITICAL();
+	{
+		/* Ensure a yield is performed if the current task is being
+		suspended. */
+		if (pxTaskToSuspend == pxCurrentTCB) {
+			pxTaskToSuspend = NULL;
+		}
+
+		/* If null is passed in here then we are suspending ourselves. */
+		pxTCB = prvGetTCBFromHandle(pxTaskToSuspend);
+
+		traceTASK_SUSPEND(pxTCB);
+
+		/* Remove task from the ready/delayed list and place in the	suspended list. */
+		vListRemove(&(pxTCB->xGenericListItem));
+
+		/* Is the task waiting on an event also? */
+		if (pxTCB->xEventListItem.pvContainer) {
+			vListRemove(&(pxTCB->xEventListItem));
+		}
+
+		vListInsertEnd((xList *) &xSuspendedTaskList, &(pxTCB->xGenericListItem));
+	}
+	portEXIT_CRITICAL();
+
+	/* We may have just suspended the current task. */
+	if ((void *) pxTaskToSuspend == NULL) {
+		portYIELD_WITHIN_API();
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+signed portBASE_TYPE xTaskIsTaskSuspended(xTaskHandle xTask)
+{
+	portBASE_TYPE xReturn = pdFALSE;
+	const tskTCB * const pxTCB = (tskTCB *) xTask;
+
+	/* Is the task we are attempting to resume actually in the
+	suspended list? */
+	if (listIS_CONTAINED_WITHIN(&xSuspendedTaskList, &(pxTCB->xGenericListItem)) != pdFALSE) {
+		/* Has the task already been resumed from within an ISR? */
+		if (listIS_CONTAINED_WITHIN(&xPendingReadyList, &(pxTCB->xEventListItem)) != pdTRUE) {
+			/* Is it in the suspended list because it is in the
+			Suspended state?  It is possible to be in the suspended
+			list because it is blocked on a task with no timeout
+			specified. */
+			if (listIS_CONTAINED_WITHIN(NULL, &(pxTCB->xEventListItem)) == pdTRUE) {
+				xReturn = pdTRUE;
+			}
+		}
+	}
+
+	return xReturn;
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+
+void vTaskResume(xTaskHandle pxTaskToResume)
+{
+	tskTCB *pxTCB;
+
+	/* Remove the task from whichever list it is currently in, and place
+	it in the ready list. */
+	pxTCB = (tskTCB *) pxTaskToResume;
+
+	/* The parameter cannot be NULL as it is impossible to resume the
+	currently executing task. */
+	if ((pxTCB != NULL) && (pxTCB != pxCurrentTCB)) {
+		portENTER_CRITICAL();
+		{
+			if (xTaskIsTaskSuspended(pxTCB) == pdTRUE) {
+				traceTASK_RESUME(pxTCB);
+
+				/* As we are in a critical section we can access the ready
+				lists even if the scheduler is suspended. */
+				vListRemove(&(pxTCB->xGenericListItem));
+				prvAddTaskToReadyQueue(pxTCB);
+
+				/* We may have just resumed a higher priority task. */
+				if (pxTCB->uxPriority >= pxCurrentTCB->uxPriority) {
+					/* This yield may not cause the task just resumed to run, but
+					will leave the lists in the correct state for the next yield. */
+					portYIELD_WITHIN_API();
+				}
+			}
+		}
+		portEXIT_CRITICAL();
+	}
+}
+
+#endif
+
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
+
+portBASE_TYPE xTaskResumeFromISR(xTaskHandle pxTaskToResume)
+{
+	portBASE_TYPE xYieldRequired = pdFALSE;
+	tskTCB *pxTCB;
+
+	pxTCB = (tskTCB *) pxTaskToResume;
+
+	if (xTaskIsTaskSuspended(pxTCB) == pdTRUE) {
+		traceTASK_RESUME_FROM_ISR(pxTCB);
+
+		if (uxSchedulerSuspended == (unsigned portBASE_TYPE) pdFALSE) {
+			xYieldRequired = (pxTCB->uxPriority >= pxCurrentTCB->uxPriority);
+			vListRemove(&(pxTCB->xGenericListItem));
+			prvAddTaskToReadyQueue(pxTCB);
+		} else {
+			/* We cannot access the delayed or ready lists, so will hold this
+			task pending until the scheduler is resumed, at which point a
+			yield will be performed if necessary. */
+			vListInsertEnd((xList *) &(xPendingReadyList), &(pxTCB->xEventListItem));
+		}
+	}
+
+	return xYieldRequired;
+}
+
+#endif
+
+
+
+
+/*-----------------------------------------------------------
+ * PUBLIC SCHEDULER CONTROL documented in task.h
+ *----------------------------------------------------------*/
+
+
+void vTaskStartScheduler(void)
+{
+	portBASE_TYPE xReturn;
+
+	/* Add the idle task at the lowest priority. */
+	xReturn = xTaskCreate(prvIdleTask, (signed char *) "IDLE", tskIDLE_STACK_SIZE, (void *) NULL, (tskIDLE_PRIORITY | portPRIVILEGE_BIT), (xTaskHandle *) NULL);
+
+	if (xReturn == pdPASS) {
+		/* Interrupts are turned off here, to ensure a tick does not occur
+		before or during the call to xPortStartScheduler().  The stacks of
+		the created tasks contain a status word with interrupts switched on
+		so interrupts will automatically get re-enabled when the first task
+		starts to run.
+
+		STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE
+		DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */
+		portDISABLE_INTERRUPTS();
+
+		xSchedulerRunning = pdTRUE;
+		xTickCount = (portTickType) 0;
+
+		/* If configGENERATE_RUN_TIME_STATS is defined then the following
+		macro must be defined to configure the timer/counter used to generate
+		the run time counter time base. */
+		portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
+
+		/* Setting up the timer tick is hardware specific and thus in the
+		portable interface. */
+		if (xPortStartScheduler()) {
+			/* Should not reach here as if the scheduler is running the
+			function will not return. */
+		} else {
+			/* Should only reach here if a task calls xTaskEndScheduler(). */
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+void vTaskEndScheduler(void)
+{
+	/* Stop the scheduler interrupts and call the portable scheduler end
+	routine so the original ISRs can be restored if necessary.  The port
+	layer must ensure interrupts enable	bit is left in the correct state. */
+	portDISABLE_INTERRUPTS();
+	xSchedulerRunning = pdFALSE;
+	vPortEndScheduler();
+}
+/*----------------------------------------------------------*/
+
+void vTaskSuspendAll(void)
+{
+	/* A critical section is not required as the variable is of type
+	portBASE_TYPE. */
+	++uxSchedulerSuspended;
+}
+/*----------------------------------------------------------*/
+
+signed portBASE_TYPE xTaskResumeAll(void)
+{
+	register tskTCB *pxTCB;
+	signed portBASE_TYPE xAlreadyYielded = pdFALSE;
+
+	/* It is possible that an ISR caused a task to be removed from an event
+	list while the scheduler was suspended.  If this was the case then the
+	removed task will have been added to the xPendingReadyList.  Once the
+	scheduler has been resumed it is safe to move all the pending ready
+	tasks from this list into their appropriate ready list. */
+	portENTER_CRITICAL();
+	{
+		--uxSchedulerSuspended;
+
+		if (uxSchedulerSuspended == (unsigned portBASE_TYPE) pdFALSE) {
+			if (uxCurrentNumberOfTasks > (unsigned portBASE_TYPE) 0) {
+				portBASE_TYPE xYieldRequired = pdFALSE;
+
+				/* Move any readied tasks from the pending list into the
+				appropriate ready list. */
+				while ((pxTCB = (tskTCB *) listGET_OWNER_OF_HEAD_ENTRY(((xList *) & xPendingReadyList))) != NULL) {
+					vListRemove(&(pxTCB->xEventListItem));
+					vListRemove(&(pxTCB->xGenericListItem));
+					prvAddTaskToReadyQueue(pxTCB);
+
+					/* If we have moved a task that has a priority higher than
+					the current task then we should yield. */
+					if (pxTCB->uxPriority >= pxCurrentTCB->uxPriority) {
+						xYieldRequired = pdTRUE;
+					}
+				}
+
+				/* If any ticks occurred while the scheduler was suspended then
+				they should be processed now.  This ensures the tick count does not
+				slip, and that any delayed tasks are resumed at the correct time. */
+				if (uxMissedTicks > (unsigned portBASE_TYPE) 0) {
+					while (uxMissedTicks > (unsigned portBASE_TYPE) 0) {
+						vTaskIncrementTick();
+						--uxMissedTicks;
+					}
+
+					/* As we have processed some ticks it is appropriate to yield
+					to ensure the highest priority task that is ready to run is
+					the task actually running. */
+#if configUSE_PREEMPTION == 1
+					{
+						xYieldRequired = pdTRUE;
+					}
+#endif
+				}
+
+				if ((xYieldRequired == pdTRUE) || (xMissedYield == pdTRUE)) {
+					xAlreadyYielded = pdTRUE;
+					xMissedYield = pdFALSE;
+					portYIELD_WITHIN_API();
+				}
+			}
+		}
+	}
+	portEXIT_CRITICAL();
+
+	return xAlreadyYielded;
+}
+
+
+
+
+
+
+/*-----------------------------------------------------------
+ * PUBLIC TASK UTILITIES documented in task.h
+ *----------------------------------------------------------*/
+
+
+
+portTickType xTaskGetTickCount(void)
+{
+	portTickType xTicks;
+
+	/* Critical section required if running on a 16 bit processor. */
+	portENTER_CRITICAL();
+	{
+		xTicks = xTickCount;
+	}
+	portEXIT_CRITICAL();
+
+	return xTicks;
+}
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxTaskGetNumberOfTasks(void)
+{
+	/* A critical section is not required because the variables are of type
+	portBASE_TYPE. */
+	return uxCurrentNumberOfTasks;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+void vTaskList(signed char *pcWriteBuffer)
+{
+	unsigned portBASE_TYPE uxQueue;
+
+	/* This is a VERY costly function that should be used for debug only.
+	It leaves interrupts disabled for a LONG time. */
+
+	vTaskSuspendAll();
+	{
+		/* Run through all the lists that could potentially contain a TCB and
+		report the task name, state and stack high water mark. */
+
+		pcWriteBuffer[ 0 ] = (signed char) 0x00;
+		strcat((char *) pcWriteBuffer, (const char *) "\r\n");
+
+		uxQueue = uxTopUsedPriority + 1;
+
+		do {
+			uxQueue--;
+
+			if (!listLIST_IS_EMPTY(&(pxReadyTasksLists[ uxQueue ]))) {
+				prvListTaskWithinSingleList(pcWriteBuffer, (xList *) &(pxReadyTasksLists[ uxQueue ]), tskREADY_CHAR);
+			}
+		} while (uxQueue > (unsigned short) tskIDLE_PRIORITY);
+
+		if (!listLIST_IS_EMPTY(pxDelayedTaskList)) {
+			prvListTaskWithinSingleList(pcWriteBuffer, (xList *) pxDelayedTaskList, tskBLOCKED_CHAR);
+		}
+
+		if (!listLIST_IS_EMPTY(pxOverflowDelayedTaskList)) {
+			prvListTaskWithinSingleList(pcWriteBuffer, (xList *) pxOverflowDelayedTaskList, tskBLOCKED_CHAR);
+		}
+
+#if( INCLUDE_vTaskDelete == 1 )
+		{
+			if (!listLIST_IS_EMPTY(&xTasksWaitingTermination)) {
+				prvListTaskWithinSingleList(pcWriteBuffer, (xList *) &xTasksWaitingTermination, tskDELETED_CHAR);
+			}
+		}
+#endif
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+		{
+			if (!listLIST_IS_EMPTY(&xSuspendedTaskList)) {
+				prvListTaskWithinSingleList(pcWriteBuffer, (xList *) &xSuspendedTaskList, tskSUSPENDED_CHAR);
+			}
+		}
+#endif
+	}
+	xTaskResumeAll();
+}
+
+#endif
+/*----------------------------------------------------------*/
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+void vTaskGetRunTimeStats(signed char *pcWriteBuffer)
+{
+	unsigned portBASE_TYPE uxQueue;
+	unsigned long ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
+
+	/* This is a VERY costly function that should be used for debug only.
+	It leaves interrupts disabled for a LONG time. */
+
+	vTaskSuspendAll();
+	{
+		/* Run through all the lists that could potentially contain a TCB,
+		generating a table of run timer percentages in the provided
+		buffer. */
+
+		pcWriteBuffer[ 0 ] = (signed char) 0x00;
+		strcat((char *) pcWriteBuffer, (const char *) "\r\n");
+
+		uxQueue = uxTopUsedPriority + 1;
+
+		do {
+			uxQueue--;
+
+			if (!listLIST_IS_EMPTY(&(pxReadyTasksLists[ uxQueue ]))) {
+				prvGenerateRunTimeStatsForTasksInList(pcWriteBuffer, (xList *) &(pxReadyTasksLists[ uxQueue ]), ulTotalRunTime);
+			}
+		} while (uxQueue > (unsigned short) tskIDLE_PRIORITY);
+
+		if (!listLIST_IS_EMPTY(pxDelayedTaskList)) {
+			prvGenerateRunTimeStatsForTasksInList(pcWriteBuffer, (xList *) pxDelayedTaskList, ulTotalRunTime);
+		}
+
+		if (!listLIST_IS_EMPTY(pxOverflowDelayedTaskList)) {
+			prvGenerateRunTimeStatsForTasksInList(pcWriteBuffer, (xList *) pxOverflowDelayedTaskList, ulTotalRunTime);
+		}
+
+#if ( INCLUDE_vTaskDelete == 1 )
+		{
+			if (!listLIST_IS_EMPTY(&xTasksWaitingTermination)) {
+				prvGenerateRunTimeStatsForTasksInList(pcWriteBuffer, (xList *) &xTasksWaitingTermination, ulTotalRunTime);
+			}
+		}
+#endif
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+		{
+			if (!listLIST_IS_EMPTY(&xSuspendedTaskList)) {
+				prvGenerateRunTimeStatsForTasksInList(pcWriteBuffer, (xList *) &xSuspendedTaskList, ulTotalRunTime);
+			}
+		}
+#endif
+	}
+	xTaskResumeAll();
+}
+
+#endif
+/*----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+void vTaskStartTrace(signed char * pcBuffer, unsigned long ulBufferSize)
+{
+	portENTER_CRITICAL();
+	{
+		pcTraceBuffer = (signed char *)pcBuffer;
+		pcTraceBufferStart = pcBuffer;
+		pcTraceBufferEnd = pcBuffer + (ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE);
+		xTracing = pdTRUE;
+	}
+	portEXIT_CRITICAL();
+}
+
+#endif
+/*----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+unsigned long ulTaskEndTrace(void)
+{
+	unsigned long ulBufferLength;
+
+	portENTER_CRITICAL();
+	xTracing = pdFALSE;
+	portEXIT_CRITICAL();
+
+	ulBufferLength = (unsigned long)(pcTraceBuffer - pcTraceBufferStart);
+
+	return ulBufferLength;
+}
+
+#endif
+
+
+
+/*-----------------------------------------------------------
+ * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
+ * documented in task.h
+ *----------------------------------------------------------*/
+
+
+void vTaskIncrementTick(void)
+{
+	/* Called by the portable layer each time a tick interrupt occurs.
+	Increments the tick then checks to see if the new tick value will cause any
+	tasks to be unblocked. */
+	if (uxSchedulerSuspended == (unsigned portBASE_TYPE) pdFALSE) {
+		++xTickCount;
+		if (xTickCount == (portTickType) 0) {
+			xList *pxTemp;
+
+			/* Tick count has overflowed so we need to swap the delay lists.
+			If there are any items in pxDelayedTaskList here then there is
+			an error! */
+			pxTemp = pxDelayedTaskList;
+			pxDelayedTaskList = pxOverflowDelayedTaskList;
+			pxOverflowDelayedTaskList = pxTemp;
+			xNumOfOverflows++;
+		}
+
+		/* See if this tick has made a timeout expire. */
+		prvCheckDelayedTasks();
+	} else {
+		++uxMissedTicks;
+
+		/* The tick hook gets called at regular intervals, even if the
+		scheduler is locked. */
+#if ( configUSE_TICK_HOOK == 1 )
+		{
+			extern void vApplicationTickHook(void);
+
+			vApplicationTickHook();
+		}
+#endif
+	}
+
+#if ( configUSE_TICK_HOOK == 1 )
+	{
+		extern void vApplicationTickHook(void);
+
+		/* Guard against the tick hook being called when the missed tick
+		count is being unwound (when the scheduler is being unlocked. */
+		if (uxMissedTicks == 0) {
+			vApplicationTickHook();
+		}
+	}
+#endif
+
+	traceTASK_INCREMENT_TICK(xTickCount);
+}
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_vTaskCleanUpResources == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
+
+void vTaskCleanUpResources(void)
+{
+	unsigned short usQueue;
+	volatile tskTCB *pxTCB;
+
+	usQueue = (unsigned short) uxTopUsedPriority + (unsigned short) 1;
+
+	/* Remove any TCB's from the ready queues. */
+	do {
+		usQueue--;
+
+		while (!listLIST_IS_EMPTY(&(pxReadyTasksLists[ usQueue ]))) {
+			listGET_OWNER_OF_NEXT_ENTRY(pxTCB, &(pxReadyTasksLists[ usQueue ]));
+			vListRemove((xListItem *) &(pxTCB->xGenericListItem));
+
+			prvDeleteTCB((tskTCB *) pxTCB);
+		}
+	} while (usQueue > (unsigned short) tskIDLE_PRIORITY);
+
+	/* Remove any TCB's from the delayed queue. */
+	while (!listLIST_IS_EMPTY(&xDelayedTaskList1)) {
+		listGET_OWNER_OF_NEXT_ENTRY(pxTCB, &xDelayedTaskList1);
+		vListRemove((xListItem *) &(pxTCB->xGenericListItem));
+
+		prvDeleteTCB((tskTCB *) pxTCB);
+	}
+
+	/* Remove any TCB's from the overflow delayed queue. */
+	while (!listLIST_IS_EMPTY(&xDelayedTaskList2)) {
+		listGET_OWNER_OF_NEXT_ENTRY(pxTCB, &xDelayedTaskList2);
+		vListRemove((xListItem *) &(pxTCB->xGenericListItem));
+
+		prvDeleteTCB((tskTCB *) pxTCB);
+	}
+
+	while (!listLIST_IS_EMPTY(&xSuspendedTaskList)) {
+		listGET_OWNER_OF_NEXT_ENTRY(pxTCB, &xSuspendedTaskList);
+		vListRemove((xListItem *) &(pxTCB->xGenericListItem));
+
+		prvDeleteTCB((tskTCB *) pxTCB);
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+void vTaskSetApplicationTaskTag(xTaskHandle xTask, pdTASK_HOOK_CODE pxTagValue)
+{
+	tskTCB *xTCB;
+
+	/* If xTask is NULL then we are setting our own task hook. */
+	if (xTask == NULL) {
+		xTCB = (tskTCB *) pxCurrentTCB;
+	} else {
+		xTCB = (tskTCB *) xTask;
+	}
+
+	/* Save the hook function in the TCB.  A critical section is required as
+	the value can be accessed from an interrupt. */
+	portENTER_CRITICAL();
+	xTCB->pxTaskTag = pxTagValue;
+	portEXIT_CRITICAL();
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+pdTASK_HOOK_CODE xTaskGetApplicationTaskTag(xTaskHandle xTask)
+{
+	tskTCB *xTCB;
+	pdTASK_HOOK_CODE xReturn;
+
+	/* If xTask is NULL then we are setting our own task hook. */
+	if (xTask == NULL) {
+		xTCB = (tskTCB *) pxCurrentTCB;
+	} else {
+		xTCB = (tskTCB *) xTask;
+	}
+
+	/* Save the hook function in the TCB.  A critical section is required as
+	the value can be accessed from an interrupt. */
+	portENTER_CRITICAL();
+	xReturn = xTCB->pxTaskTag;
+	portEXIT_CRITICAL();
+
+	return xReturn;
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+
+portBASE_TYPE xTaskCallApplicationTaskHook(xTaskHandle xTask, void *pvParameter)
+{
+	tskTCB *xTCB;
+	portBASE_TYPE xReturn;
+
+	/* If xTask is NULL then we are calling our own task hook. */
+	if (xTask == NULL) {
+		xTCB = (tskTCB *) pxCurrentTCB;
+	} else {
+		xTCB = (tskTCB *) xTask;
+	}
+
+	if (xTCB->pxTaskTag != NULL) {
+		xReturn = xTCB->pxTaskTag(pvParameter);
+	} else {
+		xReturn = pdFAIL;
+	}
+
+	return xReturn;
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+void vTaskSwitchContext(void)
+{
+	if (uxSchedulerSuspended != (unsigned portBASE_TYPE) pdFALSE) {
+		/* The scheduler is currently suspended - do not allow a context
+		switch. */
+		xMissedYield = pdTRUE;
+		return;
+	}
+
+	traceTASK_SWITCHED_OUT();
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+	{
+		unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
+
+		/* Add the amount of time the task has been running to the accumulated
+		time so far.  The time the task started running was stored in
+		ulTaskSwitchedInTime.  Note that there is no overflow protection here
+		so count values are only valid until the timer overflows.  Generally
+		this will be about 1 hour assuming a 1uS timer increment. */
+		pxCurrentTCB->ulRunTimeCounter += (ulTempCounter - ulTaskSwitchedInTime);
+		ulTaskSwitchedInTime = ulTempCounter;
+	}
+#endif
+
+	taskFIRST_CHECK_FOR_STACK_OVERFLOW();
+	taskSECOND_CHECK_FOR_STACK_OVERFLOW();
+
+	/* Find the highest priority queue that contains ready tasks. */
+	while (listLIST_IS_EMPTY(&(pxReadyTasksLists[ uxTopReadyPriority ]))) {
+		--uxTopReadyPriority;
+	}
+
+	/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the
+	same priority get an equal share of the processor time. */
+	listGET_OWNER_OF_NEXT_ENTRY(pxCurrentTCB, &(pxReadyTasksLists[ uxTopReadyPriority ]));
+
+	traceTASK_SWITCHED_IN();
+	vWriteTraceToBuffer();
+}
+/*-----------------------------------------------------------*/
+
+void vTaskPlaceOnEventList(const xList * const pxEventList, portTickType xTicksToWait)
+{
+	portTickType xTimeToWake;
+
+	/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
+	SCHEDULER SUSPENDED. */
+
+	/* Place the event list item of the TCB in the appropriate event list.
+	This is placed in the list in priority order so the highest priority task
+	is the first to be woken by the event. */
+	vListInsert((xList *) pxEventList, (xListItem *) &(pxCurrentTCB->xEventListItem));
+
+	/* We must remove ourselves from the ready list before adding ourselves
+	to the blocked list as the same list item is used for both lists.  We have
+	exclusive access to the ready lists as the scheduler is locked. */
+	vListRemove((xListItem *) &(pxCurrentTCB->xGenericListItem));
+
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+	{
+		if (xTicksToWait == portMAX_DELAY) {
+			/* Add ourselves to the suspended task list instead of a delayed task
+			list to ensure we are not woken by a timing event.  We will block
+			indefinitely. */
+			vListInsertEnd((xList *) &xSuspendedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+		} else {
+			/* Calculate the time at which the task should be woken if the event does
+			not occur.  This may overflow but this doesn't matter. */
+			xTimeToWake = xTickCount + xTicksToWait;
+
+			listSET_LIST_ITEM_VALUE(&(pxCurrentTCB->xGenericListItem), xTimeToWake);
+
+			if (xTimeToWake < xTickCount) {
+				/* Wake time has overflowed.  Place this item in the overflow list. */
+				vListInsert((xList *) pxOverflowDelayedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+			} else {
+				/* The wake time has not overflowed, so we can use the current block list. */
+				vListInsert((xList *) pxDelayedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+			}
+		}
+	}
+#else
+	{
+		/* Calculate the time at which the task should be woken if the event does
+		not occur.  This may overflow but this doesn't matter. */
+		xTimeToWake = xTickCount + xTicksToWait;
+
+		listSET_LIST_ITEM_VALUE(&(pxCurrentTCB->xGenericListItem), xTimeToWake);
+
+		if (xTimeToWake < xTickCount) {
+			/* Wake time has overflowed.  Place this item in the overflow list. */
+			vListInsert((xList *) pxOverflowDelayedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+		} else {
+			/* The wake time has not overflowed, so we can use the current block list. */
+			vListInsert((xList *) pxDelayedTaskList, (xListItem *) &(pxCurrentTCB->xGenericListItem));
+		}
+	}
+#endif
+}
+/*-----------------------------------------------------------*/
+
+signed portBASE_TYPE xTaskRemoveFromEventList(const xList * const pxEventList)
+{
+	tskTCB *pxUnblockedTCB;
+	portBASE_TYPE xReturn;
+
+	/* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
+	SCHEDULER SUSPENDED.  It can also be called from within an ISR. */
+
+	/* The event list is sorted in priority order, so we can remove the
+	first in the list, remove the TCB from the delayed list, and add
+	it to the ready list.
+
+	If an event is for a queue that is locked then this function will never
+	get called - the lock count on the queue will get modified instead.  This
+	means we can always expect exclusive access to the event list here. */
+	pxUnblockedTCB = (tskTCB *) listGET_OWNER_OF_HEAD_ENTRY(pxEventList);
+	vListRemove(&(pxUnblockedTCB->xEventListItem));
+
+	if (uxSchedulerSuspended == (unsigned portBASE_TYPE) pdFALSE) {
+		vListRemove(&(pxUnblockedTCB->xGenericListItem));
+		prvAddTaskToReadyQueue(pxUnblockedTCB);
+	} else {
+		/* We cannot access the delayed or ready lists, so will hold this
+		task pending until the scheduler is resumed. */
+		vListInsertEnd((xList *) &(xPendingReadyList), &(pxUnblockedTCB->xEventListItem));
+	}
+
+	if (pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority) {
+		/* Return true if the task removed from the event list has
+		a higher priority than the calling task.  This allows
+		the calling task to know if it should force a context
+		switch now. */
+		xReturn = pdTRUE;
+	} else {
+		xReturn = pdFALSE;
+	}
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskSetTimeOutState(xTimeOutType * const pxTimeOut)
+{
+	pxTimeOut->xOverflowCount = xNumOfOverflows;
+	pxTimeOut->xTimeOnEntering = xTickCount;
+}
+/*-----------------------------------------------------------*/
+
+portBASE_TYPE xTaskCheckForTimeOut(xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait)
+{
+	portBASE_TYPE xReturn;
+
+	portENTER_CRITICAL();
+	{
+#if ( INCLUDE_vTaskSuspend == 1 )
+		/* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
+		the maximum block time then the task should block indefinitely, and
+		therefore never time out. */
+		if (*pxTicksToWait == portMAX_DELAY) {
+			xReturn = pdFALSE;
+		} else /* We are not blocking indefinitely, perform the checks below. */
+#endif
+
+			if ((xNumOfOverflows != pxTimeOut->xOverflowCount) && ((portTickType) xTickCount >= (portTickType) pxTimeOut->xTimeOnEntering)) {
+				/* The tick count is greater than the time at which vTaskSetTimeout()
+				was called, but has also overflowed since vTaskSetTimeOut() was called.
+				It must have wrapped all the way around and gone past us again. This
+				passed since vTaskSetTimeout() was called. */
+				xReturn = pdTRUE;
+			} else if (((portTickType)((portTickType) xTickCount - (portTickType) pxTimeOut->xTimeOnEntering)) < (portTickType) *pxTicksToWait) {
+				/* Not a genuine timeout. Adjust parameters for time remaining. */
+				*pxTicksToWait -= ((portTickType) xTickCount - (portTickType) pxTimeOut->xTimeOnEntering);
+				vTaskSetTimeOutState(pxTimeOut);
+				xReturn = pdFALSE;
+			} else {
+				xReturn = pdTRUE;
+			}
+	}
+	portEXIT_CRITICAL();
+
+	return xReturn;
+}
+/*-----------------------------------------------------------*/
+
+void vTaskMissedYield(void)
+{
+	xMissedYield = pdTRUE;
+}
+
+/*
+ * -----------------------------------------------------------
+ * The Idle task.
+ * ----------------------------------------------------------
+ *
+ * The portTASK_FUNCTION() macro is used to allow port/compiler specific
+ * language extensions.  The equivalent prototype for this function is:
+ *
+ * void prvIdleTask( void *pvParameters );
+ *
+ */
+static portTASK_FUNCTION(prvIdleTask, pvParameters)
+{
+	/* Stop warnings. */
+	(void) pvParameters;
+
+	for (;;) {
+		/* See if any tasks have been deleted. */
+		prvCheckTasksWaitingTermination();
+
+#if ( configUSE_PREEMPTION == 0 )
+		{
+			/* If we are not using preemption we keep forcing a task switch to
+			see if any other task has become available.  If we are using
+			preemption we don't need to do this as any task becoming available
+			will automatically get the processor anyway. */
+			taskYIELD();
+		}
+#endif
+
+#if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
+		{
+			/* When using preemption tasks of equal priority will be
+			timesliced.  If a task that is sharing the idle priority is ready
+			to run then the idle task should yield before the end of the
+			timeslice.
+
+			A critical region is not required here as we are just reading from
+			the list, and an occasional incorrect value will not matter.  If
+			the ready list at the idle priority contains more than one task
+			then a task other than the idle task is ready to execute. */
+			if (listCURRENT_LIST_LENGTH(&(pxReadyTasksLists[ tskIDLE_PRIORITY ])) > (unsigned portBASE_TYPE) 1) {
+				taskYIELD();
+			}
+		}
+#endif
+
+#if ( configUSE_IDLE_HOOK == 1 )
+		{
+			extern void vApplicationIdleHook(void);
+
+			/* Call the user defined function from within the idle task.  This
+			allows the application designer to add background functionality
+			without the overhead of a separate task.
+			NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
+			CALL A FUNCTION THAT MIGHT BLOCK. */
+			vApplicationIdleHook();
+		}
+#endif
+	}
+} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */
+
+
+
+
+
+
+
+/*-----------------------------------------------------------
+ * File private functions documented at the top of the file.
+ *----------------------------------------------------------*/
+
+
+
+static void prvInitialiseTCBVariables(tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth)
+{
+	/* Store the function name in the TCB. */
+#if configMAX_TASK_NAME_LEN > 1
+	{
+		/* Don't bring strncpy into the build unnecessarily. */
+		strncpy((char *) pxTCB->pcTaskName, (const char *) pcName, (unsigned short) configMAX_TASK_NAME_LEN);
+	}
+#endif
+	pxTCB->pcTaskName[(unsigned short) configMAX_TASK_NAME_LEN - (unsigned short) 1 ] = '\0';
+
+	/* This is used as an array index so must ensure it's not too large.  First
+	remove the privilege bit if one is present. */
+	if (uxPriority >= configMAX_PRIORITIES) {
+		uxPriority = configMAX_PRIORITIES - 1;
+	}
+
+	pxTCB->uxPriority = uxPriority;
+#if ( configUSE_MUTEXES == 1 )
+	{
+		pxTCB->uxBasePriority = uxPriority;
+	}
+#endif
+
+	vListInitialiseItem(&(pxTCB->xGenericListItem));
+	vListInitialiseItem(&(pxTCB->xEventListItem));
+
+	/* Set the pxTCB as a link back from the xListItem.  This is so we can get
+	back to	the containing TCB from a generic item in a list. */
+	listSET_LIST_ITEM_OWNER(&(pxTCB->xGenericListItem), pxTCB);
+
+	/* Event lists are always in priority order. */
+	listSET_LIST_ITEM_VALUE(&(pxTCB->xEventListItem), configMAX_PRIORITIES - (portTickType) uxPriority);
+	listSET_LIST_ITEM_OWNER(&(pxTCB->xEventListItem), pxTCB);
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+	{
+		pxTCB->uxCriticalNesting = (unsigned portBASE_TYPE) 0;
+	}
+#endif
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+	{
+		pxTCB->pxTaskTag = NULL;
+	}
+#endif
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+	{
+		pxTCB->ulRunTimeCounter = 0UL;
+	}
+#endif
+
+#if ( portUSING_MPU_WRAPPERS == 1 )
+	{
+		vPortStoreTaskMPUSettings(&(pxTCB->xMPUSettings), xRegions, pxTCB->pxStack, usStackDepth);
+	}
+#else
+	{
+		(void) xRegions;
+		(void) usStackDepth;
+	}
+#endif
+}
+/*-----------------------------------------------------------*/
+
+#if ( portUSING_MPU_WRAPPERS == 1 )
+
+void vTaskAllocateMPURegions(xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions)
+{
+	tskTCB *pxTCB;
+
+	if (xTaskToModify == pxCurrentTCB) {
+		xTaskToModify = NULL;
+	}
+
+	/* If null is passed in here then we are deleting ourselves. */
+	pxTCB = prvGetTCBFromHandle(xTaskToModify);
+
+	vPortStoreTaskMPUSettings(&(pxTCB->xMPUSettings), xRegions, NULL, 0);
+}
+/*-----------------------------------------------------------*/
+#endif
+
+static void prvInitialiseTaskLists(void)
+{
+	unsigned portBASE_TYPE uxPriority;
+
+	for (uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++) {
+		vListInitialise((xList *) &(pxReadyTasksLists[ uxPriority ]));
+	}
+
+	vListInitialise((xList *) &xDelayedTaskList1);
+	vListInitialise((xList *) &xDelayedTaskList2);
+	vListInitialise((xList *) &xPendingReadyList);
+
+#if ( INCLUDE_vTaskDelete == 1 )
+	{
+		vListInitialise((xList *) &xTasksWaitingTermination);
+	}
+#endif
+
+#if ( INCLUDE_vTaskSuspend == 1 )
+	{
+		vListInitialise((xList *) &xSuspendedTaskList);
+	}
+#endif
+
+	/* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
+	using list2. */
+	pxDelayedTaskList = &xDelayedTaskList1;
+	pxOverflowDelayedTaskList = &xDelayedTaskList2;
+}
+/*-----------------------------------------------------------*/
+
+static void prvCheckTasksWaitingTermination(void)
+{
+#if ( INCLUDE_vTaskDelete == 1 )
+	{
+		portBASE_TYPE xListIsEmpty;
+
+		/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
+		too often in the idle task. */
+		if (uxTasksDeleted > (unsigned portBASE_TYPE) 0) {
+			vTaskSuspendAll();
+			xListIsEmpty = listLIST_IS_EMPTY(&xTasksWaitingTermination);
+			xTaskResumeAll();
+
+			if (!xListIsEmpty) {
+				tskTCB *pxTCB;
+
+				portENTER_CRITICAL();
+				{
+					pxTCB = (tskTCB *) listGET_OWNER_OF_HEAD_ENTRY(((xList *) & xTasksWaitingTermination));
+					vListRemove(&(pxTCB->xGenericListItem));
+					--uxCurrentNumberOfTasks;
+					--uxTasksDeleted;
+				}
+				portEXIT_CRITICAL();
+
+				prvDeleteTCB(pxTCB);
+			}
+		}
+	}
+#endif
+}
+/*-----------------------------------------------------------*/
+
+static tskTCB *prvAllocateTCBAndStack(unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer)
+{
+	tskTCB *pxNewTCB;
+
+	/* Allocate space for the TCB.  Where the memory comes from depends on
+	the implementation of the port malloc function. */
+	pxNewTCB = (tskTCB *) pvPortMalloc(sizeof(tskTCB));
+
+	if (pxNewTCB != NULL) {
+		/* Allocate space for the stack used by the task being created.
+		The base of the stack memory stored in the TCB so the task can
+		be deleted later if required. */
+		pxNewTCB->pxStack = (portSTACK_TYPE *) pvPortMallocAligned((((size_t)usStackDepth) * sizeof(portSTACK_TYPE)), puxStackBuffer);
+
+		if (pxNewTCB->pxStack == NULL) {
+			/* Could not allocate the stack.  Delete the allocated TCB. */
+			vPortFree(pxNewTCB);
+			pxNewTCB = NULL;
+		} else {
+			/* Just to help debugging. */
+			memset(pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof(portSTACK_TYPE));
+		}
+	}
+
+	return pxNewTCB;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TRACE_FACILITY == 1 )
+
+static void prvListTaskWithinSingleList(const signed char *pcWriteBuffer, xList *pxList, signed char cStatus)
+{
+	volatile tskTCB *pxNextTCB, *pxFirstTCB;
+	unsigned short usStackRemaining;
+
+	/* Write the details of all the TCB's in pxList into the buffer. */
+	listGET_OWNER_OF_NEXT_ENTRY(pxFirstTCB, pxList);
+	do {
+		listGET_OWNER_OF_NEXT_ENTRY(pxNextTCB, pxList);
+#if ( portSTACK_GROWTH > 0 )
+		{
+			usStackRemaining = usTaskCheckFreeStackSpace((unsigned char *) pxNextTCB->pxEndOfStack);
+		}
+#else
+		{
+			usStackRemaining = usTaskCheckFreeStackSpace((unsigned char *) pxNextTCB->pxStack);
+		}
+#endif
+
+		sprintf(pcStatusString, (char *) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, (unsigned int) pxNextTCB->uxPriority, usStackRemaining, (unsigned int) pxNextTCB->uxTCBNumber);
+		strcat((char *) pcWriteBuffer, (char *) pcStatusString);
+
+	} while (pxNextTCB != pxFirstTCB);
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configGENERATE_RUN_TIME_STATS == 1 )
+
+static void prvGenerateRunTimeStatsForTasksInList(const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime)
+{
+	volatile tskTCB *pxNextTCB, *pxFirstTCB;
+	unsigned long ulStatsAsPercentage;
+
+	/* Write the run time stats of all the TCB's in pxList into the buffer. */
+	listGET_OWNER_OF_NEXT_ENTRY(pxFirstTCB, pxList);
+	do {
+		/* Get next TCB in from the list. */
+		listGET_OWNER_OF_NEXT_ENTRY(pxNextTCB, pxList);
+
+		/* Divide by zero check. */
+		if (ulTotalRunTime > 0UL) {
+			/* Has the task run at all? */
+			if (pxNextTCB->ulRunTimeCounter == 0) {
+				/* The task has used no CPU time at all. */
+				sprintf(pcStatsString, (char *) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName);
+			} else {
+				/* What percentage of the total run time as the task used?
+				This will always be rounded down to the nearest integer. */
+				ulStatsAsPercentage = (100UL * pxNextTCB->ulRunTimeCounter) / ulTotalRunTime;
+
+				if (ulStatsAsPercentage > 0UL) {
+					sprintf(pcStatsString, (char *) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, (unsigned int) pxNextTCB->ulRunTimeCounter, (unsigned int) ulStatsAsPercentage);
+				} else {
+					/* If the percentage is zero here then the task has
+					consumed less than 1% of the total run time. */
+					sprintf(pcStatsString, (char *) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, (unsigned int) pxNextTCB->ulRunTimeCounter);
+				}
+			}
+
+			strcat((char *) pcWriteBuffer, (char *) pcStatsString);
+		}
+
+	} while (pxNextTCB != pxFirstTCB);
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+
+static unsigned short usTaskCheckFreeStackSpace(const unsigned char * pucStackByte)
+{
+	register unsigned short usCount = 0;
+
+	while (*pucStackByte == tskSTACK_FILL_BYTE) {
+		pucStackByte -= portSTACK_GROWTH;
+		usCount++;
+	}
+
+	usCount /= sizeof(portSTACK_TYPE);
+
+	return usCount;
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
+
+unsigned portBASE_TYPE uxTaskGetStackHighWaterMark(xTaskHandle xTask)
+{
+	tskTCB *pxTCB;
+	unsigned char *pcEndOfStack;
+	unsigned portBASE_TYPE uxReturn;
+
+	pxTCB = prvGetTCBFromHandle(xTask);
+
+#if portSTACK_GROWTH < 0
+	{
+		pcEndOfStack = (unsigned char *) pxTCB->pxStack;
+	}
+#else
+	{
+		pcEndOfStack = (unsigned char *) pxTCB->pxEndOfStack;
+	}
+#endif
+
+	uxReturn = (unsigned portBASE_TYPE) usTaskCheckFreeStackSpace(pcEndOfStack);
+
+	return uxReturn;
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
+
+static void prvDeleteTCB(tskTCB *pxTCB)
+{
+	/* Free up the memory allocated by the scheduler for the task.  It is up to
+	the task to free any memory allocated at the application level. */
+	vPortFreeAligned(pxTCB->pxStack);
+	vPortFree(pxTCB);
+}
+
+#endif
+
+
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 )
+
+xTaskHandle xTaskGetCurrentTaskHandle(void)
+{
+	xTaskHandle xReturn;
+
+	/* A critical section is not required as this is not called from
+	an interrupt and the current TCB will always be the same for any
+	individual execution thread. */
+	xReturn = pxCurrentTCB;
+
+	return xReturn;
+}
+
+#endif
+
+/*-----------------------------------------------------------*/
+
+#if ( INCLUDE_xTaskGetSchedulerState == 1 )
+
+portBASE_TYPE xTaskGetSchedulerState(void)
+{
+	portBASE_TYPE xReturn;
+
+	if (xSchedulerRunning == pdFALSE) {
+		xReturn = taskSCHEDULER_NOT_STARTED;
+	} else {
+		if (uxSchedulerSuspended == (unsigned portBASE_TYPE) pdFALSE) {
+			xReturn = taskSCHEDULER_RUNNING;
+		} else {
+			xReturn = taskSCHEDULER_SUSPENDED;
+		}
+	}
+
+	return xReturn;
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+void vTaskPriorityInherit(xTaskHandle * const pxMutexHolder)
+{
+	tskTCB * const pxTCB = (tskTCB *) pxMutexHolder;
+
+	if (pxTCB->uxPriority < pxCurrentTCB->uxPriority) {
+		/* Adjust the mutex holder state to account for its new priority. */
+		listSET_LIST_ITEM_VALUE(&(pxTCB->xEventListItem), configMAX_PRIORITIES - (portTickType) pxCurrentTCB->uxPriority);
+
+		/* If the task being modified is in the ready state it will need to
+		be moved in to a new list. */
+		if (listIS_CONTAINED_WITHIN(&(pxReadyTasksLists[ pxTCB->uxPriority ]), &(pxTCB->xGenericListItem))) {
+			vListRemove(&(pxTCB->xGenericListItem));
+
+			/* Inherit the priority before being moved into the new list. */
+			pxTCB->uxPriority = pxCurrentTCB->uxPriority;
+			prvAddTaskToReadyQueue(pxTCB);
+		} else {
+			/* Just inherit the priority. */
+			pxTCB->uxPriority = pxCurrentTCB->uxPriority;
+		}
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_MUTEXES == 1 )
+
+void vTaskPriorityDisinherit(xTaskHandle * const pxMutexHolder)
+{
+	tskTCB * const pxTCB = (tskTCB *) pxMutexHolder;
+
+	if (pxMutexHolder != NULL) {
+		if (pxTCB->uxPriority != pxTCB->uxBasePriority) {
+			/* We must be the running task to be able to give the mutex back.
+			Remove ourselves from the ready list we currently appear in. */
+			vListRemove(&(pxTCB->xGenericListItem));
+
+			/* Disinherit the priority before adding ourselves into the new
+			ready list. */
+			pxTCB->uxPriority = pxTCB->uxBasePriority;
+			listSET_LIST_ITEM_VALUE(&(pxTCB->xEventListItem), configMAX_PRIORITIES - (portTickType) pxTCB->uxPriority);
+			prvAddTaskToReadyQueue(pxTCB);
+		}
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+
+void vTaskEnterCritical(void)
+{
+	portDISABLE_INTERRUPTS();
+
+	if (xSchedulerRunning != pdFALSE) {
+		pxCurrentTCB->uxCriticalNesting++;
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+#if ( portCRITICAL_NESTING_IN_TCB == 1 )
+
+void vTaskExitCritical(void)
+{
+	if (xSchedulerRunning != pdFALSE) {
+		if (pxCurrentTCB->uxCriticalNesting > 0) {
+			pxCurrentTCB->uxCriticalNesting--;
+
+			if (pxCurrentTCB->uxCriticalNesting == 0) {
+				portENABLE_INTERRUPTS();
+			}
+		}
+	}
+}
+
+#endif
+/*-----------------------------------------------------------*/
+
+
+
+
diff --git a/gyro_board/src/usb/FreeRTOSConfig.h b/gyro_board/src/usb/FreeRTOSConfig.h
new file mode 100644
index 0000000..5a46dad
--- /dev/null
+++ b/gyro_board/src/usb/FreeRTOSConfig.h
@@ -0,0 +1,159 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+#include "LPC17xx.h"
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *----------------------------------------------------------*/
+
+#define configUSE_PREEMPTION		1
+#define configUSE_IDLE_HOOK		0
+#define configMAX_PRIORITIES		((unsigned portBASE_TYPE) 5)
+#define configUSE_TICK_HOOK		1
+#define configCPU_CLOCK_HZ		((unsigned long) 100000000)
+#define configTICK_RATE_HZ		((portTickType ) 1000)
+#define configMINIMAL_STACK_SIZE	((unsigned short) 80)
+#define configTOTAL_HEAP_SIZE		((size_t) (19 * 1024))
+#define configMAX_TASK_NAME_LEN		(12)
+#define configUSE_TRACE_FACILITY	1
+#define configUSE_16_BIT_TICKS		0
+#define configIDLE_SHOULD_YIELD		0
+#define configUSE_CO_ROUTINES 		0
+#define configUSE_MUTEXES		1
+
+#define configMAX_CO_ROUTINE_PRIORITIES (2)
+
+#define configUSE_COUNTING_SEMAPHORES 	0
+#define configUSE_ALTERNATIVE_API 	0
+#define configCHECK_FOR_STACK_OVERFLOW	2
+#define configUSE_RECURSIVE_MUTEXES	1
+#define configQUEUE_REGISTRY_SIZE	10
+#define configGENERATE_RUN_TIME_STATS	1
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+
+#define INCLUDE_vTaskPrioritySet		1
+#define INCLUDE_uxTaskPriorityGet		1
+#define INCLUDE_vTaskDelete			1
+#define INCLUDE_vTaskCleanUpResources		0
+#define INCLUDE_vTaskSuspend			1
+#define INCLUDE_vTaskDelayUntil			1
+#define INCLUDE_vTaskDelay			1
+#define INCLUDE_uxTaskGetStackHighWaterMark	1
+
+/*-----------------------------------------------------------
+ * Ethernet configuration.
+ *-----------------------------------------------------------*/
+
+/* MAC address configuration. */
+#define configMAC_ADDR0	0x00
+#define configMAC_ADDR1	0x12
+#define configMAC_ADDR2	0x13
+#define configMAC_ADDR3	0x10
+#define configMAC_ADDR4	0x15
+#define configMAC_ADDR5	0x11
+
+/* IP address configuration. */
+#define configIP_ADDR0		192
+#define configIP_ADDR1		168
+#define configIP_ADDR2		0
+#define configIP_ADDR3		201
+
+/* Netmask configuration. */
+#define configNET_MASK0		255
+#define configNET_MASK1		255
+#define configNET_MASK2		255
+#define configNET_MASK3		0
+
+/* Use the system definition, if there is one */
+#ifdef __NVIC_PRIO_BITS
+#define configPRIO_BITS       __NVIC_PRIO_BITS
+#else
+#define configPRIO_BITS       5        /* 32 priority levels */
+#endif
+
+/* The lowest priority. */
+#define configKERNEL_INTERRUPT_PRIORITY 	(31 << (8 - configPRIO_BITS))
+/* Priority 5, or 160 as only the top three bits are implemented. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	(5 << (8 - configPRIO_BITS))
+
+/* Priorities passed to NVIC_SetPriority() do not require shifting as the
+function does the shifting itself.  Note these priorities need to be equal to
+or lower than configMAX_SYSCALL_INTERRUPT_PRIORITY - therefore the numeric
+value needs to be equal to or greater than 5 (on the Cortex M3 the lower the
+numeric value the higher the interrupt priority). */
+#define configEMAC_INTERRUPT_PRIORITY		5
+#define configCAN_INTERRUPT_PRIORITY		5
+#define configUSB_INTERRUPT_PRIORITY		6
+
+
+
+/*-----------------------------------------------------------
+ * Macros required to setup the timer for the run time stats.
+ *-----------------------------------------------------------*/
+extern void vConfigureTimerForRunTimeStats(void);
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats()
+#define portGET_RUN_TIME_COUNTER_VALUE() TIM0->TC
+
+#endif /* FREERTOS_CONFIG_H */
diff --git a/gyro_board/src/usb/LPC17xx.h b/gyro_board/src/usb/LPC17xx.h
new file mode 100644
index 0000000..1743027
--- /dev/null
+++ b/gyro_board/src/usb/LPC17xx.h
@@ -0,0 +1,1052 @@
+#ifndef __LPC17xx_H
+#define __LPC17xx_H
+
+/* System Control Block (SCB) includes:
+   Flash Accelerator Module, Clocking and Power Control, External Interrupts,
+   Reset, System Control and Status
+*/
+#define SCB_BASE_ADDR   0x400FC000
+
+#define PCONP_PCTIM0    0x00000002
+#define PCONP_PCTIM1    0x00000004
+#define PCONP_PCUART0   0x00000008
+#define PCONP_PCUART1   0x00000010
+#define PCONP_PCPWM1    0x00000040
+#define PCONP_PCI2C0    0x00000080
+#define PCONP_PCSPI     0x00000100
+#define PCONP_PCRTC     0x00000200
+#define PCONP_PCSSP1    0x00000400
+#define PCONP_PCAD      0x00001000
+#define PCONP_PCCAN1    0x00002000
+#define PCONP_PCCAN2    0x00004000
+#define PCONP_PCGPIO    0x00008000
+#define PCONP_PCRIT     0x00010000
+#define PCONP_PCMCPWM   0x00020000
+#define PCONP_PCQEI     0x00040000
+#define PCONP_PCI2C1    0x00080000
+#define PCONP_PCSSP0    0x00200000
+#define PCONP_PCTIM2    0x00400000
+#define PCONP_PCTIM3    0x00800000
+#define PCONP_PCUART2   0x01000000
+#define PCONP_PCUART3   0x02000000
+#define PCONP_PCI2C2    0x04000000
+#define PCONP_PCI2S     0x08000000
+#define PCONP_PCGPDMA   0x20000000
+#define PCONP_PCENET    0x40000000
+#define PCONP_PCUSB     0x80000000
+
+#define PLLCON_PLLE     0x00000001
+#define PLLCON_PLLC     0x00000002
+#define PLLCON_MASK     0x00000003
+
+#define PLLCFG_MUL1     0x00000000
+#define PLLCFG_MUL2     0x00000001
+#define PLLCFG_MUL3     0x00000002
+#define PLLCFG_MUL4     0x00000003
+#define PLLCFG_MUL5     0x00000004
+#define PLLCFG_MUL6     0x00000005
+#define PLLCFG_MUL7     0x00000006
+#define PLLCFG_MUL8     0x00000007
+#define PLLCFG_MUL9     0x00000008
+#define PLLCFG_MUL10    0x00000009
+#define PLLCFG_MUL11    0x0000000A
+#define PLLCFG_MUL12    0x0000000B
+#define PLLCFG_MUL13    0x0000000C
+#define PLLCFG_MUL14    0x0000000D
+#define PLLCFG_MUL15    0x0000000E
+#define PLLCFG_MUL16    0x0000000F
+#define PLLCFG_MUL17    0x00000010
+#define PLLCFG_MUL18    0x00000011
+#define PLLCFG_MUL19    0x00000012
+#define PLLCFG_MUL20    0x00000013
+#define PLLCFG_MUL21    0x00000014
+#define PLLCFG_MUL22    0x00000015
+#define PLLCFG_MUL23    0x00000016
+#define PLLCFG_MUL24    0x00000017
+#define PLLCFG_MUL25    0x00000018
+#define PLLCFG_MUL26    0x00000019
+#define PLLCFG_MUL27    0x0000001A
+#define PLLCFG_MUL28    0x0000001B
+#define PLLCFG_MUL29    0x0000001C
+#define PLLCFG_MUL30    0x0000001D
+#define PLLCFG_MUL31    0x0000001E
+#define PLLCFG_MUL32    0x0000001F
+#define PLLCFG_MUL33    0x00000020
+#define PLLCFG_MUL34    0x00000021
+#define PLLCFG_MUL35    0x00000022
+#define PLLCFG_MUL36    0x00000023
+
+#define PLLCFG_DIV1     0x00000000
+#define PLLCFG_DIV2     0x00010000
+#define PLLCFG_DIV3     0x00020000
+#define PLLCFG_DIV4     0x00030000
+#define PLLCFG_DIV5     0x00040000
+#define PLLCFG_DIV6     0x00050000
+#define PLLCFG_DIV7     0x00060000
+#define PLLCFG_DIV8     0x00070000
+#define PLLCFG_DIV9     0x00080000
+#define PLLCFG_DIV10    0x00090000
+#define PLLCFG_MASK		0x00FF7FFF
+
+#define PLLSTAT_MSEL_MASK	0x00007FFF
+#define PLLSTAT_NSEL_MASK	0x00FF0000
+
+#define PLLSTAT_PLLE	(1 << 24)
+#define PLLSTAT_PLLC	(1 << 25)
+#define PLLSTAT_PLOCK	(1 << 26)
+
+#define PLLFEED_FEED1   0x000000AA
+#define PLLFEED_FEED2   0x00000055
+
+#define NVIC_IRQ_WDT         0u         // IRQ0,  exception number 16
+#define NVIC_IRQ_TIMER0      1u         // IRQ1,  exception number 17
+#define NVIC_IRQ_TIMER1      2u         // IRQ2,  exception number 18
+#define NVIC_IRQ_TIMER2      3u         // IRQ3,  exception number 19
+#define NVIC_IRQ_TIMER3      4u         // IRQ4,  exception number 20
+#define NVIC_IRQ_UART0       5u         // IRQ5,  exception number 21
+#define NVIC_IRQ_UART1       6u         // IRQ6,  exception number 22
+#define NVIC_IRQ_UART2       7u         // IRQ7,  exception number 23
+#define NVIC_IRQ_UART3       8u         // IRQ8,  exception number 24
+#define NVIC_IRQ_PWM1        9u         // IRQ9,  exception number 25
+#define NVIC_IRQ_I2C0        10u        // IRQ10, exception number 26
+#define NVIC_IRQ_I2C1        11u        // IRQ11, exception number 27
+#define NVIC_IRQ_I2C2        12u        // IRQ12, exception number 28
+#define NVIC_IRQ_SPI         13u        // IRQ13, exception number 29
+#define NVIC_IRQ_SSP0        14u        // IRQ14, exception number 30
+#define NVIC_IRQ_SSP1        15u        // IRQ15, exception number 31
+#define NVIC_IRQ_PLL0        16u        // IRQ16, exception number 32
+#define NVIC_IRQ_RTC         17u        // IRQ17, exception number 33
+#define NVIC_IRQ_EINT0       18u        // IRQ18, exception number 34
+#define NVIC_IRQ_EINT1       19u        // IRQ19, exception number 35
+#define NVIC_IRQ_EINT2       20u        // IRQ20, exception number 36
+#define NVIC_IRQ_EINT3       21u        // IRQ21, exception number 37
+#define NVIC_IRQ_ADC         22u        // IRQ22, exception number 38
+#define NVIC_IRQ_BOD         23u        // IRQ23, exception number 39
+#define NVIC_IRQ_USB         24u        // IRQ24, exception number 40
+#define NVIC_IRQ_CAN         25u        // IRQ25, exception number 41
+#define NVIC_IRQ_GPDMA       26u        // IRQ26, exception number 42
+#define NVIC_IRQ_I2S         27u        // IRQ27, exception number 43
+#define NVIC_IRQ_ETHERNET    28u        // IRQ28, exception number 44
+#define NVIC_IRQ_RIT         29u        // IRQ29, exception number 45
+#define NVIC_IRQ_MCPWM       30u        // IRQ30, exception number 46
+#define NVIC_IRQ_QE          31u        // IRQ31, exception number 47
+#define NVIC_IRQ_PLL1        32u        // IRQ32, exception number 48
+#define NVIC_IRQ_USB_ACT     33u        // IRQ33, exception number 49
+#define NVIC_IRQ_CAN_ACT     34u        // IRQ34, exception number 50
+
+
+#endif  // __LPC17xx_H
+
+
+#ifndef CMSIS_17xx_H
+#define CMSIS_17xx_H
+
+/******************************************************************************
+ * @file:    LPC17xx.h
+ * @purpose: CMSIS Cortex-M3 Core Peripheral Access Layer Header File for
+ *           NXP LPC17xx Device Series
+ * @version: V1.1
+ * @date:    14th May 2009
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2008 ARM Limited. All rights reserved.
+ *
+ * ARM Limited (ARM) is supplying this software for use with Cortex-M3
+ * processor based microcontrollers.  This file can be freely distributed
+ * within development tools that are supporting such ARM based processors.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ *
+ ******************************************************************************/
+
+
+#ifndef __LPC17xx_H__
+#define __LPC17xx_H__
+
+/*
+ * ==========================================================================
+ * ---------- Interrupt Number Definition -----------------------------------
+ * ==========================================================================
+ */
+
+typedef enum IRQn {
+        /******  Cortex-M3 Processor Exceptions Numbers ***************************************************/
+        NonMaskableInt_IRQn           = -14,      /*!< 2 Non Maskable Interrupt                         */
+        MemoryManagement_IRQn         = -12,      /*!< 4 Cortex-M3 Memory Management Interrupt          */
+        BusFault_IRQn                 = -11,      /*!< 5 Cortex-M3 Bus Fault Interrupt                  */
+        UsageFault_IRQn               = -10,      /*!< 6 Cortex-M3 Usage Fault Interrupt                */
+        SVCall_IRQn                   = -5,       /*!< 11 Cortex-M3 SV Call Interrupt                   */
+        DebugMonitor_IRQn             = -4,       /*!< 12 Cortex-M3 Debug Monitor Interrupt             */
+        PendSV_IRQn                   = -2,       /*!< 14 Cortex-M3 Pend SV Interrupt                   */
+        SysTick_IRQn                  = -1,       /*!< 15 Cortex-M3 System Tick Interrupt               */
+
+        /******  LPC17xx Specific Interrupt Numbers *******************************************************/
+        WDT_IRQn                      = 0,        /*!< Watchdog Timer Interrupt                         */
+        TIMER0_IRQn                   = 1,        /*!< Timer0 Interrupt                                 */
+        TIMER1_IRQn                   = 2,        /*!< Timer1 Interrupt                                 */
+        TIMER2_IRQn                   = 3,        /*!< Timer2 Interrupt                                 */
+        TIMER3_IRQn                   = 4,        /*!< Timer3 Interrupt                                 */
+        UART0_IRQn                    = 5,        /*!< UART0 Interrupt                                  */
+        UART1_IRQn                    = 6,        /*!< UART1 Interrupt                                  */
+        UART2_IRQn                    = 7,        /*!< UART2 Interrupt                                  */
+        UART3_IRQn                    = 8,        /*!< UART3 Interrupt                                  */
+        PWM1_IRQn                     = 9,        /*!< PWM1 Interrupt                                   */
+        I2C0_IRQn                     = 10,       /*!< I2C0 Interrupt                                   */
+        I2C1_IRQn                     = 11,       /*!< I2C1 Interrupt                                   */
+        I2C2_IRQn                     = 12,       /*!< I2C2 Interrupt                                   */
+        SPI_IRQn                      = 13,       /*!< SPI Interrupt                                    */
+        SSP0_IRQn                     = 14,       /*!< SSP0 Interrupt                                   */
+        SSP1_IRQn                     = 15,       /*!< SSP1 Interrupt                                   */
+        PLL0_IRQn                     = 16,       /*!< PLL0 Lock (Main PLL) Interrupt                   */
+        RTC_IRQn                      = 17,       /*!< Real Time Clock Interrupt                        */
+        EINT0_IRQn                    = 18,       /*!< External Interrupt 0 Interrupt                   */
+        EINT1_IRQn                    = 19,       /*!< External Interrupt 1 Interrupt                   */
+        EINT2_IRQn                    = 20,       /*!< External Interrupt 2 Interrupt                   */
+        EINT3_IRQn                    = 21,       /*!< External Interrupt 3 Interrupt                   */
+        ADC_IRQn                      = 22,       /*!< A/D Converter Interrupt                          */
+        BOD_IRQn                      = 23,       /*!< Brown-Out Detect Interrupt                       */
+        USB_IRQn                      = 24,       /*!< USB Interrupt                                    */
+        CAN_IRQn                      = 25,       /*!< CAN Interrupt                                    */
+        DMA_IRQn                      = 26,       /*!< General Purpose DMA Interrupt                    */
+        I2S_IRQn                      = 27,       /*!< I2S Interrupt                                    */
+        ENET_IRQn                     = 28,       /*!< Ethernet Interrupt                               */
+        RIT_IRQn                      = 29,       /*!< Repetitive Interrupt Timer Interrupt             */
+        MCPWM_IRQn                    = 30,       /*!< Motor Control PWM Interrupt                      */
+        QEI_IRQn                      = 31,       /*!< Quadrature Encoder Interface Interrupt           */
+        PLL1_IRQn                     = 32,       /*!< PLL1 Lock (USB PLL) Interrupt                    */
+} IRQn_Type;
+
+
+/*
+ * ==========================================================================
+ * ----------- Processor and Core Peripheral Section ------------------------
+ * ==========================================================================
+ */
+
+/* Configuration of the Cortex-M3 Processor and Core Peripherals */
+#define __MPU_PRESENT             1         /*!< MPU present or not                               */
+#define __NVIC_PRIO_BITS          5         /*!< Number of Bits used for Priority Levels          */
+#define __Vendor_SysTickConfig    0         /*!< Set to 1 if different SysTick Config is used     */
+
+
+//#include "..\core_cm3.h"                    /* Cortex-M3 processor and core peripherals           */
+#include "core_cm3.h"
+#include "system_LPC17xx.h"                 /* System Header                                      */
+
+
+
+/**
+ * Initialize the system clock
+ *
+ * @param  none
+ * @return none
+ *
+ * @brief  Setup the microcontroller system.
+ *         Initialize the System and update the SystemFrequency variable.
+ */
+extern void SystemInit(void);
+
+
+/******************************************************************************/
+/*                Device Specific Peripheral registers structures             */
+/******************************************************************************/
+
+/*------------- System Control (SC) ------------------------------------------*/
+typedef struct {
+        __IO uint32_t FLASHCFG;               /* Flash Accelerator Module           */
+        uint32_t RESERVED0[31];
+        __IO uint32_t PLL0CON;                /* Clocking and Power Control         */
+        __IO uint32_t PLL0CFG;
+        __I  uint32_t PLL0STAT;
+        __O  uint32_t PLL0FEED;
+        uint32_t RESERVED1[4];
+        __IO uint32_t PLL1CON;
+        __IO uint32_t PLL1CFG;
+        __I  uint32_t PLL1STAT;
+        __O  uint32_t PLL1FEED;
+        uint32_t RESERVED2[4];
+        __IO uint32_t PCON;
+        __IO uint32_t PCONP;
+        uint32_t RESERVED3[15];
+        __IO uint32_t CCLKCFG;
+        __IO uint32_t USBCLKCFG;
+        __IO uint32_t CLKSRCSEL;
+        uint32_t RESERVED4[12];
+        __IO uint32_t EXTINT;                 /* External Interrupts                */
+        uint32_t RESERVED5;
+        __IO uint32_t EXTMODE;
+        __IO uint32_t EXTPOLAR;
+        uint32_t RESERVED6[12];
+        __IO uint32_t RSID;                   /* Reset                              */
+        uint32_t RESERVED7[7];
+        __IO uint32_t SCS;                    /* Syscon Miscellaneous Registers     */
+        __IO uint32_t IRCTRIM;                /* Clock Dividers                     */
+        __IO uint32_t PCLKSEL0;
+        __IO uint32_t PCLKSEL1;
+        uint32_t RESERVED8[4];
+        __IO uint32_t USBIntSt;               /* USB Device/OTG Interrupt Register  */
+        uint32_t RESERVED9;
+        __IO uint32_t CLKOUTCFG;              /* Clock Output Configuration         */
+} SC_TypeDef;
+
+/*------------- Pin Connect Block (PINCON) -----------------------------------*/
+typedef struct {
+        __IO uint32_t PINSEL0;
+        __IO uint32_t PINSEL1;
+        __IO uint32_t PINSEL2;
+        __IO uint32_t PINSEL3;
+        __IO uint32_t PINSEL4;
+        __IO uint32_t PINSEL5;
+        __IO uint32_t PINSEL6;
+        __IO uint32_t PINSEL7;
+        __IO uint32_t PINSEL8;
+        __IO uint32_t PINSEL9;
+        __IO uint32_t PINSEL10;
+        uint32_t RESERVED0[5];
+        __IO uint32_t PINMODE0;
+        __IO uint32_t PINMODE1;
+        __IO uint32_t PINMODE2;
+        __IO uint32_t PINMODE3;
+        __IO uint32_t PINMODE4;
+        __IO uint32_t PINMODE5;
+        __IO uint32_t PINMODE6;
+        __IO uint32_t PINMODE7;
+        __IO uint32_t PINMODE8;
+        __IO uint32_t PINMODE9;
+        __IO uint32_t PINMODE_OD0;
+        __IO uint32_t PINMODE_OD1;
+        __IO uint32_t PINMODE_OD2;
+        __IO uint32_t PINMODE_OD3;
+        __IO uint32_t PINMODE_OD4;
+} PINCON_TypeDef;
+
+/*------------- General Purpose Input/Output (GPIO) --------------------------*/
+typedef struct {
+        __IO uint32_t FIODIR;
+        uint32_t RESERVED0[3];
+        __IO uint32_t FIOMASK;
+        __IO uint32_t FIOPIN;
+        __IO uint32_t FIOSET;
+        __O  uint32_t FIOCLR;
+} GPIO_TypeDef;
+
+typedef struct {
+        __I  uint32_t IntStatus;
+        __I  uint32_t IO0IntStatR;
+        __I  uint32_t IO0IntStatF;
+        __O  uint32_t IO0IntClr;
+        __IO uint32_t IO0IntEnR;
+        __IO uint32_t IO0IntEnF;
+        uint32_t RESERVED0[3];
+        __I  uint32_t IO2IntStatR;
+        __I  uint32_t IO2IntStatF;
+        __O  uint32_t IO2IntClr;
+        __IO uint32_t IO2IntEnR;
+        __IO uint32_t IO2IntEnF;
+} GPIOINT_TypeDef;
+
+/*------------- Timer (TIM) --------------------------------------------------*/
+typedef struct {
+        __IO uint32_t IR;
+        __IO uint32_t TCR;
+        __IO uint32_t TC;
+        __IO uint32_t PR;
+        __IO uint32_t PC;
+        __IO uint32_t MCR;
+        __IO uint32_t MR0;
+        __IO uint32_t MR1;
+        __IO uint32_t MR2;
+        __IO uint32_t MR3;
+        __IO uint32_t CCR;
+        __I  uint32_t CR0;
+        __I  uint32_t CR1;
+        uint32_t RESERVED0[2];
+        __IO uint32_t EMR;
+        uint32_t RESERVED1[24];
+        __IO uint32_t CTCR;
+} TIM_TypeDef;
+
+/*------------- Pulse-Width Modulation (PWM) ---------------------------------*/
+typedef struct {
+        __IO uint32_t IR;
+        __IO uint32_t TCR;
+        __IO uint32_t TC;
+        __IO uint32_t PR;
+        __IO uint32_t PC;
+        __IO uint32_t MCR;
+        __IO uint32_t MR0;
+        __IO uint32_t MR1;
+        __IO uint32_t MR2;
+        __IO uint32_t MR3;
+        __IO uint32_t CCR;
+        __I  uint32_t CR0;
+        __I  uint32_t CR1;
+        __I  uint32_t CR2;
+        __I  uint32_t CR3;
+        __IO uint32_t MR4;
+        __IO uint32_t MR5;
+        __IO uint32_t MR6;
+        __IO uint32_t PCR;
+        __IO uint32_t LER;
+        uint32_t RESERVED0[7];
+        __IO uint32_t CTCR;
+} PWM_TypeDef;
+
+/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/
+typedef struct {
+        union {
+                __I  uint8_t  RBR;
+                __O  uint8_t  THR;
+                __IO uint8_t  DLL;
+                uint32_t RESERVED0;
+        };
+        union {
+                __IO uint8_t  DLM;
+                __IO uint32_t IER;
+        };
+        union {
+                __I  uint32_t IIR;
+                __O  uint8_t  FCR;
+        };
+        __IO uint8_t  LCR;
+        uint8_t  RESERVED1[7];
+        __IO uint8_t  LSR;
+        uint8_t  RESERVED2[7];
+        __IO uint8_t  SCR;
+        uint8_t  RESERVED3[3];
+        __IO uint32_t ACR;
+        __IO uint8_t  ICR;
+        uint8_t  RESERVED4[3];
+        __IO uint8_t  FDR;
+        uint8_t  RESERVED5[7];
+        __IO uint8_t  TER;
+        uint8_t  RESERVED6[27];
+        __IO uint8_t  RS485CTRL;
+        uint8_t  RESERVED7[3];
+        __IO uint8_t  ADRMATCH;
+} UART_TypeDef;
+
+typedef struct {
+        union {
+                __I  uint8_t  RBR;
+                __O  uint8_t  THR;
+                __IO uint8_t  DLL;
+                uint32_t RESERVED0;
+        };
+        union {
+                __IO uint8_t  DLM;
+                __IO uint32_t IER;
+        };
+        union {
+                __I  uint32_t IIR;
+                __O  uint8_t  FCR;
+        };
+        __IO uint8_t  LCR;
+        uint8_t  RESERVED1[3];
+        __IO uint8_t  MCR;
+        uint8_t  RESERVED2[3];
+        __IO uint8_t  LSR;
+        uint8_t  RESERVED3[3];
+        __IO uint8_t  MSR;
+        uint8_t  RESERVED4[3];
+        __IO uint8_t  SCR;
+        uint8_t  RESERVED5[3];
+        __IO uint32_t ACR;
+        uint32_t RESERVED6;
+        __IO uint32_t FDR;
+        uint32_t RESERVED7;
+        __IO uint8_t  TER;
+        uint8_t  RESERVED8[27];
+        __IO uint8_t  RS485CTRL;
+        uint8_t  RESERVED9[3];
+        __IO uint8_t  ADRMATCH;
+        uint8_t  RESERVED10[3];
+        __IO uint8_t  RS485DLY;
+} UART1_TypeDef;
+
+/*------------- Serial Peripheral Interface (SPI) ----------------------------*/
+typedef struct {
+        __IO uint32_t SPCR;
+        __I  uint32_t SPSR;
+        __IO uint32_t SPDR;
+        __IO uint32_t SPCCR;
+        uint32_t RESERVED0[3];
+        __IO uint32_t SPINT;
+} SPI_TypeDef;
+
+/*------------- Synchronous Serial Communication (SSP) -----------------------*/
+typedef struct {
+        __IO uint32_t CR0;
+        __IO uint32_t CR1;
+        __IO uint32_t DR;
+        __I  uint32_t SR;
+        __IO uint32_t CPSR;
+        __IO uint32_t IMSC;
+        __IO uint32_t RIS;
+        __IO uint32_t MIS;
+        __IO uint32_t ICR;
+        __IO uint32_t DMACR;
+} SSP_TypeDef;
+
+/*------------- Inter-Integrated Circuit (I2C) -------------------------------*/
+typedef struct {
+        __IO uint32_t I2CONSET;
+        __I  uint32_t I2STAT;
+        __IO uint32_t I2DAT;
+        __IO uint32_t I2ADR0;
+        __IO uint32_t I2SCLH;
+        __IO uint32_t I2SCLL;
+        __O  uint32_t I2CONCLR;
+        __IO uint32_t MMCTRL;
+        __IO uint32_t I2ADR1;
+        __IO uint32_t I2ADR2;
+        __IO uint32_t I2ADR3;
+        __I  uint32_t I2DATA_BUFFER;
+        __IO uint32_t I2MASK0;
+        __IO uint32_t I2MASK1;
+        __IO uint32_t I2MASK2;
+        __IO uint32_t I2MASK3;
+} I2C_TypeDef;
+
+/*------------- Inter IC Sound (I2S) -----------------------------------------*/
+typedef struct {
+        __IO uint32_t I2SDAO;
+        __IO  uint32_t I2SDAI;
+        __O  uint32_t I2STXFIFO;
+        __I  uint32_t I2SRXFIFO;
+        __I  uint32_t I2SSTATE;
+        __IO uint32_t I2SDMA1;
+        __IO uint32_t I2SDMA2;
+        __IO uint32_t I2SIRQ;
+        __IO uint32_t I2STXRATE;
+        __IO uint32_t I2SRXRATE;
+        __IO uint32_t I2STXBITRATE;
+        __IO uint32_t I2SRXBITRATE;
+        __IO uint32_t I2STXMODE;
+        __IO uint32_t I2SRXMODE;
+} I2S_TypeDef;
+
+/*------------- Repetitive Interrupt Timer (RIT) -----------------------------*/
+typedef struct {
+        __IO uint32_t RICOMPVAL;
+        __IO uint32_t RIMASK;
+        __IO uint8_t  RICTRL;
+        uint8_t  RESERVED0[3];
+        __IO uint32_t RICOUNTER;
+} RIT_TypeDef;
+
+/*------------- Real-Time Clock (RTC) ----------------------------------------*/
+typedef struct {
+        __IO uint8_t  ILR;
+        uint8_t  RESERVED0[3];
+        __IO uint8_t  CCR;
+        uint8_t  RESERVED1[3];
+        __IO uint8_t  CIIR;
+        uint8_t  RESERVED2[3];
+        __IO uint8_t  AMR;
+        uint8_t  RESERVED3[3];
+        __I  uint32_t CTIME0;
+        __I  uint32_t CTIME1;
+        __I  uint32_t CTIME2;
+        __IO uint8_t  SEC;
+        uint8_t  RESERVED4[3];
+        __IO uint8_t  MIN;
+        uint8_t  RESERVED5[3];
+        __IO uint8_t  HOUR;
+        uint8_t  RESERVED6[3];
+        __IO uint8_t  DOM;
+        uint8_t  RESERVED7[3];
+        __IO uint8_t  DOW;
+        uint8_t  RESERVED8[3];
+        __IO uint16_t DOY;
+        uint16_t RESERVED9;
+        __IO uint8_t  MONTH;
+        uint8_t  RESERVED10[3];
+        __IO uint16_t YEAR;
+        uint16_t RESERVED11;
+        __IO uint32_t CALIBRATION;
+        __IO uint32_t GPREG0;
+        __IO uint32_t GPREG1;
+        __IO uint32_t GPREG2;
+        __IO uint32_t GPREG3;
+        __IO uint32_t GPREG4;
+        __IO uint8_t  WAKEUPDIS;
+        uint8_t  RESERVED12[3];
+        __IO uint8_t  PWRCTRL;
+        uint8_t  RESERVED13[3];
+        __IO uint8_t  ALSEC;
+        uint8_t  RESERVED14[3];
+        __IO uint8_t  ALMIN;
+        uint8_t  RESERVED15[3];
+        __IO uint8_t  ALHOUR;
+        uint8_t  RESERVED16[3];
+        __IO uint8_t  ALDOM;
+        uint8_t  RESERVED17[3];
+        __IO uint8_t  ALDOW;
+        uint8_t  RESERVED18[3];
+        __IO uint16_t ALDOY;
+        uint16_t RESERVED19;
+        __IO uint8_t  ALMON;
+        uint8_t  RESERVED20[3];
+        __IO uint16_t ALYEAR;
+        uint16_t RESERVED21;
+} RTC_TypeDef;
+
+/*------------- Watchdog Timer (WDT) -----------------------------------------*/
+typedef struct {
+        __IO uint8_t  WDMOD;
+        uint8_t  RESERVED0[3];
+        __IO uint32_t WDTC;
+        __O  uint8_t  WDFEED;
+        uint8_t  RESERVED1[3];
+        __I  uint32_t WDTV;
+        __IO uint32_t WDCLKSEL;
+} WDT_TypeDef;
+
+/*------------- Analog-to-Digital Converter (ADC) ----------------------------*/
+typedef struct {
+        __IO uint32_t ADCR;
+        __IO uint32_t ADGDR;
+        uint32_t RESERVED0;
+        __IO uint32_t ADINTEN;
+        __I  uint32_t ADDR0;
+        __I  uint32_t ADDR1;
+        __I  uint32_t ADDR2;
+        __I  uint32_t ADDR3;
+        __I  uint32_t ADDR4;
+        __I  uint32_t ADDR5;
+        __I  uint32_t ADDR6;
+        __I  uint32_t ADDR7;
+        __I  uint32_t ADSTAT;
+        __IO uint32_t ADTRM;
+} ADC_TypeDef;
+
+/*------------- Digital-to-Analog Converter (DAC) ----------------------------*/
+typedef struct {
+        __IO uint32_t DACR;
+        __IO uint32_t DACCTRL;
+        __IO uint16_t DACCNTVAL;
+} DAC_TypeDef;
+
+/*------------- Motor Control Pulse-Width Modulation (MCPWM) -----------------*/
+typedef struct {
+        __I  uint32_t MCCON;
+        __O  uint32_t MCCON_SET;
+        __O  uint32_t MCCON_CLR;
+        __I  uint32_t MCCAPCON;
+        __O  uint32_t MCCAPCON_SET;
+        __O  uint32_t MCCAPCON_CLR;
+        __IO uint32_t MCTC0;
+        __IO uint32_t MCTC1;
+        __IO uint32_t MCTC2;
+        __IO uint32_t MCLIM0;
+        __IO uint32_t MCLIM1;
+        __IO uint32_t MCLIM2;
+        __IO uint32_t MCMAT0;
+        __IO uint32_t MCMAT1;
+        __IO uint32_t MCMAT2;
+        __IO uint32_t MCDEADTIME;
+        __IO uint32_t MCCP;
+        __IO uint32_t MCCR0;
+        __IO uint32_t MCCR1;
+        __IO uint32_t MCCR2;
+        __I  uint32_t MCINTEN;
+        __O  uint32_t MCINTEN_SET;
+        __O  uint32_t MCINTEN_CLR;
+        __I  uint32_t MCCNTCON;
+        __O  uint32_t MCCNTCON_SET;
+        __O  uint32_t MCCNTCON_CLR;
+        __I  uint32_t MCINTFLAG;
+        __O  uint32_t MCINTFLAG_SET;
+        __O  uint32_t MCINTFLAG_CLR;
+        __O  uint32_t MCCAP_CLR;
+} MCPWM_TypeDef;
+
+/*------------- Quadrature Encoder Interface (QEI) ---------------------------*/
+typedef struct {
+        __O  uint32_t QEICON;
+        __I  uint32_t QEISTAT;
+        __IO uint32_t QEICONF;
+        __I  uint32_t QEIPOS;
+        __IO uint32_t QEIMAXPOS;
+        __IO uint32_t CMPOS0;
+        __IO uint32_t CMPOS1;
+        __IO uint32_t CMPOS2;
+        __I  uint32_t INXCNT;
+        __IO uint32_t INXCMP;
+        __IO uint32_t QEILOAD;
+        __I  uint32_t QEITIME;
+        __I  uint32_t QEIVEL;
+        __I  uint32_t QEICAP;
+        __IO uint32_t VELCOMP;
+        __IO uint32_t FILTER;
+        uint32_t RESERVED0[998];
+        __O  uint32_t QEIIEC;
+        __O  uint32_t QEIIES;
+        __I  uint32_t QEIINTSTAT;
+        __I  uint32_t QEIIE;
+        __O  uint32_t QEICLR;
+        __O  uint32_t QEISET;
+} QEI_TypeDef;
+
+/*------------- Controller Area Network (CAN) --------------------------------*/
+typedef struct {
+        __IO uint32_t mask[512];              /* ID Masks                           */
+} CANAF_RAM_TypeDef;
+
+typedef struct {                        /* Acceptance Filter Registers        */
+        __IO uint32_t AFMR;
+        __IO uint32_t SFF_sa;
+        __IO uint32_t SFF_GRP_sa;
+        __IO uint32_t EFF_sa;
+        __IO uint32_t EFF_GRP_sa;
+        __IO uint32_t ENDofTable;
+        __I  uint32_t LUTerrAd;
+        __I  uint32_t LUTerr;
+} CANAF_TypeDef;
+
+typedef struct {                        /* Central Registers                  */
+        __I  uint32_t CANTxSR;
+        __I  uint32_t CANRxSR;
+        __I  uint32_t CANMSR;
+} CANCR_TypeDef;
+
+typedef struct {                        /* Controller Registers               */
+        __IO uint32_t MOD;
+        __O  uint32_t CMR;
+        __IO uint32_t GSR;
+        __I  uint32_t ICR;
+        __IO uint32_t IER;
+        __IO uint32_t BTR;
+        __IO uint32_t EWL;
+        __I  uint32_t SR;
+        __IO uint32_t RFS;
+        __IO uint32_t RID;
+        __IO uint32_t RDA;
+        __IO uint32_t RDB;
+        __IO uint32_t TFI1;
+        __IO uint32_t TID1;
+        __IO uint32_t TDA1;
+        __IO uint32_t TDB1;
+        __IO uint32_t TFI2;
+        __IO uint32_t TID2;
+        __IO uint32_t TDA2;
+        __IO uint32_t TDB2;
+        __IO uint32_t TFI3;
+        __IO uint32_t TID3;
+        __IO uint32_t TDA3;
+        __IO uint32_t TDB3;
+} CAN_TypeDef;
+
+/*------------- General Purpose Direct Memory Access (GPDMA) -----------------*/
+typedef struct {                        /* Common Registers                   */
+        __I  uint32_t DMACIntStat;
+        __I  uint32_t DMACIntTCStat;
+        __O  uint32_t DMACIntTCClear;
+        __I  uint32_t DMACIntErrStat;
+        __O  uint32_t DMACIntErrClr;
+        __I  uint32_t DMACRawIntTCStat;
+        __I  uint32_t DMACRawIntErrStat;
+        __I  uint32_t DMACEnbldChns;
+        __IO uint32_t DMACSoftBReq;
+        __IO uint32_t DMACSoftSReq;
+        __IO uint32_t DMACSoftLBReq;
+        __IO uint32_t DMACSoftLSReq;
+        __IO uint32_t DMACConfig;
+        __IO uint32_t DMACSync;
+} GPDMA_TypeDef;
+
+typedef struct {                        /* Channel Registers                  */
+        __IO uint32_t DMACCSrcAddr;
+        __IO uint32_t DMACCDestAddr;
+        __IO uint32_t DMACCLLI;
+        __IO uint32_t DMACCControl;
+        __IO uint32_t DMACCConfig;
+} GPDMACH_TypeDef;
+
+/*------------- Universal Serial Bus (USB) -----------------------------------*/
+typedef struct {
+        __I  uint32_t HcRevision;             /* USB Host Registers                 */
+        __IO uint32_t HcControl;
+        __IO uint32_t HcCommandStatus;
+        __IO uint32_t HcInterruptStatus;
+        __IO uint32_t HcInterruptEnable;
+        __IO uint32_t HcInterruptDisable;
+        __IO uint32_t HcHCCA;
+        __I  uint32_t HcPeriodCurrentED;
+        __IO uint32_t HcControlHeadED;
+        __IO uint32_t HcControlCurrentED;
+        __IO uint32_t HcBulkHeadED;
+        __IO uint32_t HcBulkCurrentED;
+        __I  uint32_t HcDoneHead;
+        __IO uint32_t HcFmInterval;
+        __I  uint32_t HcFmRemaining;
+        __I  uint32_t HcFmNumber;
+        __IO uint32_t HcPeriodicStart;
+        __IO uint32_t HcLSTreshold;
+        __IO uint32_t HcRhDescriptorA;
+        __IO uint32_t HcRhDescriptorB;
+        __IO uint32_t HcRhStatus;
+        __IO uint32_t HcRhPortStatus1;
+        __IO uint32_t HcRhPortStatus2;
+        uint32_t RESERVED0[40];
+        __I  uint32_t Module_ID;
+
+        __I  uint32_t OTGIntSt;               /* USB On-The-Go Registers            */
+        __IO uint32_t OTGIntEn;
+        __O  uint32_t OTGIntSet;
+        __O  uint32_t OTGIntClr;
+        __IO uint32_t OTGStCtrl;
+        __IO uint32_t OTGTmr;
+        uint32_t RESERVED1[58];
+
+        __I  uint32_t USBDevIntSt;            /* USB Device Interrupt Registers     */
+        __IO uint32_t USBDevIntEn;
+        __O  uint32_t USBDevIntClr;
+        __O  uint32_t USBDevIntSet;
+
+        __O  uint32_t USBCmdCode;             /* USB Device SIE Command Registers   */
+        __I  uint32_t USBCmdData;
+
+        __I  uint32_t USBRxData;              /* USB Device Transfer Registers      */
+        __O  uint32_t USBTxData;
+        __I  uint32_t USBRxPLen;
+        __O  uint32_t USBTxPLen;
+        __IO uint32_t USBCtrl;
+        __O  uint32_t USBDevIntPri;
+
+        __I  uint32_t USBEpIntSt;             /* USB Device Endpoint Interrupt Regs */
+        __IO uint32_t USBEpIntEn;
+        __O  uint32_t USBEpIntClr;
+        __O  uint32_t USBEpIntSet;
+        __O  uint32_t USBEpIntPri;
+
+        __IO uint32_t USBReEp;                /* USB Device Endpoint Realization Reg*/
+        __O  uint32_t USBEpInd;
+        __IO uint32_t USBMaxPSize;
+
+        __I  uint32_t USBDMARSt;              /* USB Device DMA Registers           */
+        __O  uint32_t USBDMARClr;
+        __O  uint32_t USBDMARSet;
+        uint32_t RESERVED2[9];
+        __IO uint32_t USBUDCAH;
+        __I  uint32_t USBEpDMASt;
+        __O  uint32_t USBEpDMAEn;
+        __O  uint32_t USBEpDMADis;
+        __I  uint32_t USBDMAIntSt;
+        __IO uint32_t USBDMAIntEn;
+        uint32_t RESERVED3[2];
+        __I  uint32_t USBEoTIntSt;
+        __O  uint32_t USBEoTIntClr;
+        __O  uint32_t USBEoTIntSet;
+        __I  uint32_t USBNDDRIntSt;
+        __O  uint32_t USBNDDRIntClr;
+        __O  uint32_t USBNDDRIntSet;
+        __I  uint32_t USBSysErrIntSt;
+        __O  uint32_t USBSysErrIntClr;
+        __O  uint32_t USBSysErrIntSet;
+        uint32_t RESERVED4[15];
+
+        __I  uint32_t I2C_RX;                 /* USB OTG I2C Registers              */
+        __O  uint32_t I2C_WO;
+        __I  uint32_t I2C_STS;
+        __IO uint32_t I2C_CTL;
+        __IO uint32_t I2C_CLKHI;
+        __O  uint32_t I2C_CLKLO;
+        uint32_t RESERVED5[823];
+
+        union {
+                __IO uint32_t USBClkCtrl;             /* USB Clock Control Registers        */
+                __IO uint32_t OTGClkCtrl;
+        } ;
+        union {
+                __I  uint32_t USBClkSt;
+                __I  uint32_t OTGClkSt;
+        };
+} USB_TypeDef;
+
+/*------------- Ethernet Media Access Controller (EMAC) ----------------------*/
+typedef struct {
+        __IO uint32_t MAC1;                   /* MAC Registers                      */
+        __IO uint32_t MAC2;
+        __IO uint32_t IPGT;
+        __IO uint32_t IPGR;
+        __IO uint32_t CLRT;
+        __IO uint32_t MAXF;
+        __IO uint32_t SUPP;
+        __IO uint32_t TEST;
+        __IO uint32_t MCFG;
+        __IO uint32_t MCMD;
+        __IO uint32_t MADR;
+        __O  uint32_t MWTD;
+        __I  uint32_t MRDD;
+        __I  uint32_t MIND;
+        uint32_t RESERVED0[2];
+        __IO uint32_t SA0;
+        __IO uint32_t SA1;
+        __IO uint32_t SA2;
+        uint32_t RESERVED1[45];
+        __IO uint32_t Command;                /* Control Registers                  */
+        __I  uint32_t Status;
+        __IO uint32_t RxDescriptor;
+        __IO uint32_t RxStatus;
+        __IO uint32_t RxDescriptorNumber;
+        __I  uint32_t RxProduceIndex;
+        __IO uint32_t RxConsumeIndex;
+        __IO uint32_t TxDescriptor;
+        __IO uint32_t TxStatus;
+        __IO uint32_t TxDescriptorNumber;
+        __IO uint32_t TxProduceIndex;
+        __I  uint32_t TxConsumeIndex;
+        uint32_t RESERVED2[10];
+        __I  uint32_t TSV0;
+        __I  uint32_t TSV1;
+        __I  uint32_t RSV;
+        uint32_t RESERVED3[3];
+        __IO uint32_t FlowControlCounter;
+        __I  uint32_t FlowControlStatus;
+        uint32_t RESERVED4[34];
+        __IO uint32_t RxFilterCtrl;           /* Rx Filter Registers                */
+        __IO uint32_t RxFilterWoLStatus;
+        __IO uint32_t RxFilterWoLClear;
+        uint32_t RESERVED5;
+        __IO uint32_t HashFilterL;
+        __IO uint32_t HashFilterH;
+        uint32_t RESERVED6[882];
+        __I  uint32_t IntStatus;              /* Module Control Registers           */
+        __IO uint32_t IntEnable;
+        __O  uint32_t IntClear;
+        __O  uint32_t IntSet;
+        uint32_t RESERVED7;
+        __IO uint32_t PowerDown;
+        uint32_t RESERVED8;
+        __IO uint32_t Module_ID;
+} EMAC_TypeDef;
+
+/******************************************************************************/
+/*                         Peripheral memory map                              */
+/******************************************************************************/
+/* Base addresses                                                             */
+#define FLASH_BASE            (0x00000000UL)
+#define RAM_BASE              (0x10000000UL)
+#define GPIO_BASE             (0x2009C000UL)
+#define APB0_BASE             (0x40000000UL)
+#define APB1_BASE             (0x40080000UL)
+#define AHB_BASE              (0x50000000UL)
+#define CM3_BASE              (0xE0000000UL)
+
+/* APB0 peripherals                                                           */
+#define WDT_BASE              (APB0_BASE + 0x00000)
+#define TIM0_BASE             (APB0_BASE + 0x04000)
+#define TIM1_BASE             (APB0_BASE + 0x08000)
+#define UART0_BASE            (APB0_BASE + 0x0C000)
+#define UART1_BASE            (APB0_BASE + 0x10000)
+#define PWM1_BASE             (APB0_BASE + 0x18000)
+#define I2C0_BASE             (APB0_BASE + 0x1C000)
+#define SPI_BASE              (APB0_BASE + 0x20000)
+#define RTC_BASE              (APB0_BASE + 0x24000)
+#define GPIOINT_BASE          (APB0_BASE + 0x28080)
+#define PINCON_BASE           (APB0_BASE + 0x2C000)
+#define SSP1_BASE             (APB0_BASE + 0x30000)
+#define ADC_BASE              (APB0_BASE + 0x34000)
+#define CANAF_RAM_BASE        (APB0_BASE + 0x38000)
+#define CANAF_BASE            (APB0_BASE + 0x3C000)
+#define CANCR_BASE            (APB0_BASE + 0x40000)
+#define CAN1_BASE             (APB0_BASE + 0x44000)
+#define CAN2_BASE             (APB0_BASE + 0x48000)
+#define I2C1_BASE             (APB0_BASE + 0x5C000)
+
+/* APB1 peripherals                                                           */
+#define SSP0_BASE             (APB1_BASE + 0x08000)
+#define DAC_BASE              (APB1_BASE + 0x0C000)
+#define TIM2_BASE             (APB1_BASE + 0x10000)
+#define TIM3_BASE             (APB1_BASE + 0x14000)
+#define UART2_BASE            (APB1_BASE + 0x18000)
+#define UART3_BASE            (APB1_BASE + 0x1C000)
+#define I2C2_BASE             (APB1_BASE + 0x20000)
+#define I2S_BASE              (APB1_BASE + 0x28000)
+#define RIT_BASE              (APB1_BASE + 0x30000)
+#define MCPWM_BASE            (APB1_BASE + 0x38000)
+#define QEI_BASE              (APB1_BASE + 0x3C000)
+#define SC_BASE               (APB1_BASE + 0x7C000)
+
+/* AHB peripherals                                                            */
+#define EMAC_BASE             (AHB_BASE  + 0x00000)
+#define GPDMA_BASE            (AHB_BASE  + 0x04000)
+#define GPDMACH0_BASE         (AHB_BASE  + 0x04100)
+#define GPDMACH1_BASE         (AHB_BASE  + 0x04120)
+#define GPDMACH2_BASE         (AHB_BASE  + 0x04140)
+#define GPDMACH3_BASE         (AHB_BASE  + 0x04160)
+#define GPDMACH4_BASE         (AHB_BASE  + 0x04180)
+#define GPDMACH5_BASE         (AHB_BASE  + 0x041A0)
+#define GPDMACH6_BASE         (AHB_BASE  + 0x041C0)
+#define GPDMACH7_BASE         (AHB_BASE  + 0x041E0)
+#define USB_BASE              (AHB_BASE  + 0x0C000)
+
+/* GPIOs                                                                      */
+#define GPIO0_BASE            (GPIO_BASE + 0x00000)
+#define GPIO1_BASE            (GPIO_BASE + 0x00020)
+#define GPIO2_BASE            (GPIO_BASE + 0x00040)
+#define GPIO3_BASE            (GPIO_BASE + 0x00060)
+#define GPIO4_BASE            (GPIO_BASE + 0x00080)
+
+
+/******************************************************************************/
+/*                         Peripheral declaration                             */
+/******************************************************************************/
+#define SC                    ((       SC_TypeDef *)        SC_BASE)
+#define GPIO0                 ((     GPIO_TypeDef *)     GPIO0_BASE)
+#define GPIO1                 ((     GPIO_TypeDef *)     GPIO1_BASE)
+#define GPIO2                 ((     GPIO_TypeDef *)     GPIO2_BASE)
+#define GPIO3                 ((     GPIO_TypeDef *)     GPIO3_BASE)
+#define GPIO4                 ((     GPIO_TypeDef *)     GPIO4_BASE)
+#define WDT                   ((      WDT_TypeDef *)       WDT_BASE)
+#define TIM0                  ((      TIM_TypeDef *)      TIM0_BASE)
+#define TIM1                  ((      TIM_TypeDef *)      TIM1_BASE)
+#define TIM2                  ((      TIM_TypeDef *)      TIM2_BASE)
+#define TIM3                  ((      TIM_TypeDef *)      TIM3_BASE)
+#define RIT                   ((      RIT_TypeDef *)       RIT_BASE)
+#define UART0                 ((     UART_TypeDef *)     UART0_BASE)
+#define UART1                 ((    UART1_TypeDef *)     UART1_BASE)
+#define UART2                 ((     UART_TypeDef *)     UART2_BASE)
+#define UART3                 ((     UART_TypeDef *)     UART3_BASE)
+#define PWM1                  ((      PWM_TypeDef *)      PWM1_BASE)
+#define I2C0                  ((      I2C_TypeDef *)      I2C0_BASE)
+#define I2C1                  ((      I2C_TypeDef *)      I2C1_BASE)
+#define I2C2                  ((      I2C_TypeDef *)      I2C2_BASE)
+#define I2S                   ((      I2S_TypeDef *)       I2S_BASE)
+#define SPI                   ((      SPI_TypeDef *)       SPI_BASE)
+#define RTC                   ((      RTC_TypeDef *)       RTC_BASE)
+#define GPIOINT               ((  GPIOINT_TypeDef *)   GPIOINT_BASE)
+#define PINCON                ((   PINCON_TypeDef *)    PINCON_BASE)
+#define SSP0                  ((      SSP_TypeDef *)      SSP0_BASE)
+#define SSP1                  ((      SSP_TypeDef *)      SSP1_BASE)
+#define ADC                   ((      ADC_TypeDef *)       ADC_BASE)
+#define DAC                   ((      DAC_TypeDef *)       DAC_BASE)
+#define CANAF_RAM             ((CANAF_RAM_TypeDef *) CANAF_RAM_BASE)
+#define CANAF                 ((    CANAF_TypeDef *)     CANAF_BASE)
+#define CANCR                 ((    CANCR_TypeDef *)     CANCR_BASE)
+#define CAN1                  ((      CAN_TypeDef *)      CAN1_BASE)
+#define CAN2                  ((      CAN_TypeDef *)      CAN2_BASE)
+#define MCPWM                 ((    MCPWM_TypeDef *)     MCPWM_BASE)
+#define QEI                   ((      QEI_TypeDef *)       QEI_BASE)
+#define EMAC                  ((     EMAC_TypeDef *)      EMAC_BASE)
+#define GPDMA                 ((    GPDMA_TypeDef *)     GPDMA_BASE)
+#define GPDMACH0              ((  GPDMACH_TypeDef *)  GPDMACH0_BASE)
+#define GPDMACH1              ((  GPDMACH_TypeDef *)  GPDMACH1_BASE)
+#define GPDMACH2              ((  GPDMACH_TypeDef *)  GPDMACH2_BASE)
+#define GPDMACH3              ((  GPDMACH_TypeDef *)  GPDMACH3_BASE)
+#define GPDMACH4              ((  GPDMACH_TypeDef *)  GPDMACH4_BASE)
+#define GPDMACH5              ((  GPDMACH_TypeDef *)  GPDMACH5_BASE)
+#define GPDMACH6              ((  GPDMACH_TypeDef *)  GPDMACH6_BASE)
+#define GPDMACH7              ((  GPDMACH_TypeDef *)  GPDMACH7_BASE)
+#define USB                   ((      USB_TypeDef *)       USB_BASE)
+
+#endif  // __LPC17xx_H__
+
+
+#endif
diff --git a/gyro_board/src/usb/LPCUSB/USB_CDC.c b/gyro_board/src/usb/LPCUSB/USB_CDC.c
new file mode 100644
index 0000000..47d28db
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/USB_CDC.c
@@ -0,0 +1,454 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+	Minimal implementation of a USB serial port, using the CDC class.
+	This example application simply echoes everything it receives right back
+	to the host.
+
+	Windows:
+	Extract the usbser.sys file from .cab file in C:\WINDOWS\Driver Cache\i386
+	and store it somewhere (C:\temp is a good place) along with the usbser.inf
+	file. Then plug in the LPC176x and direct windows to the usbser driver.
+	Windows then creates an extra COMx port that you can open in a terminal
+	program, like hyperterminal. [Note for FreeRTOS users - the required .inf
+	file is included in the project directory.]
+
+	Linux:
+	The device should be recognised automatically by the cdc_acm driver,
+	which creates a /dev/ttyACMx device file that acts just like a regular
+	serial port.
+
+*/
+
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "task.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "usbapi.h"
+#include "usbdebug.h"
+#include "usbstruct.h"
+
+#include "LPC17xx.h"
+
+#define usbMAX_SEND_BLOCK		( 20 / portTICK_RATE_MS )
+#define usbRXBUFFER_LEN			( 80 )
+#define usbTXBUFFER_LEN			( 600 )
+
+#define INCREMENT_ECHO_BY 0
+#define BAUD_RATE	115200
+
+#define INT_IN_EP		0x81
+#define BULK_OUT_EP		0x05
+#define BULK_IN_EP		0x82
+
+#define MAX_PACKET_SIZE	64
+
+#define LE_WORD(x)		((x)&0xFF),((x)>>8)
+
+// CDC definitions
+#define CS_INTERFACE			0x24
+#define CS_ENDPOINT				0x25
+
+#define	SET_LINE_CODING			0x20
+#define	GET_LINE_CODING			0x21
+#define	SET_CONTROL_LINE_STATE	0x22
+
+// data structure for GET_LINE_CODING / SET_LINE_CODING class requests
+typedef struct {
+	unsigned long		dwDTERate;
+	unsigned char		bCharFormat;
+	unsigned char		bParityType;
+	unsigned char		bDataBits;
+} TLineCoding;
+
+static TLineCoding LineCoding = {115200, 0, 0, 8};
+static unsigned char abBulkBuf[64];
+static unsigned char abClassReqData[8];
+
+static xQueueHandle xRxedChars = NULL, xCharsForTx = NULL;
+
+// forward declaration of interrupt handler
+void USBIntHandler(void);
+
+static const unsigned char abDescriptors[] = {
+
+// device descriptor
+	0x12,
+	DESC_DEVICE,
+	LE_WORD(0x0101),		// bcdUSB
+	0x02,				// bDeviceClass
+	0x00,				// bDeviceSubClass
+	0x00,				// bDeviceProtocol
+	MAX_PACKET_SIZE0,		// bMaxPacketSize
+	LE_WORD(0xFFFF),		// idVendor
+	LE_WORD(0x0005),		// idProduct
+	LE_WORD(0x0100),		// bcdDevice
+	0x01,				// iManufacturer
+	0x02,				// iProduct
+	0x03,				// iSerialNumber
+	0x01,				// bNumConfigurations
+
+// configuration descriptor
+	0x09,
+	DESC_CONFIGURATION,
+	LE_WORD(67),			// wTotalLength
+	0x02,				// bNumInterfaces
+	0x01,				// bConfigurationValue
+	0x00,				// iConfiguration
+	0xC0,				// bmAttributes
+	0x32,				// bMaxPower
+// control class interface
+	0x09,
+	DESC_INTERFACE,
+	0x00,				// bInterfaceNumber
+	0x00,				// bAlternateSetting
+	0x01,				// bNumEndPoints
+	0x02,				// bInterfaceClass
+	0x02,				// bInterfaceSubClass
+	0x01,				// bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
+	0x00,				// iInterface
+// header functional descriptor
+	0x05,
+	CS_INTERFACE,
+	0x00,
+	LE_WORD(0x0110),
+// call management functional descriptor
+	0x05,
+	CS_INTERFACE,
+	0x01,
+	0x01,				// bmCapabilities = device handles call management
+	0x01,				// bDataInterface
+// ACM functional descriptor
+	0x04,
+	CS_INTERFACE,
+	0x02,
+	0x02,				// bmCapabilities
+// union functional descriptor
+	0x05,
+	CS_INTERFACE,
+	0x06,
+	0x00,				// bMasterInterface
+	0x01,				// bSlaveInterface0
+// notification EP
+	0x07,
+	DESC_ENDPOINT,
+	INT_IN_EP,			// bEndpointAddress
+	0x03,				// bmAttributes = intr
+	LE_WORD(8),			// wMaxPacketSize
+	0x0A,				// bInterval
+// data class interface descriptor
+	0x09,
+	DESC_INTERFACE,
+	0x01,				// bInterfaceNumber
+	0x00,				// bAlternateSetting
+	0x02,				// bNumEndPoints
+	0x0A,				// bInterfaceClass = data
+	0x00,				// bInterfaceSubClass
+	0x00,				// bInterfaceProtocol
+	0x00,				// iInterface
+// data EP OUT
+	0x07,
+	DESC_ENDPOINT,
+	BULK_OUT_EP,			// bEndpointAddress
+	0x02,				// bmAttributes = bulk
+	LE_WORD(MAX_PACKET_SIZE),	// wMaxPacketSize
+	0x00,				// bInterval
+// data EP in
+	0x07,
+	DESC_ENDPOINT,
+	BULK_IN_EP,			// bEndpointAddress
+	0x02,				// bmAttributes = bulk
+	LE_WORD(MAX_PACKET_SIZE),	// wMaxPacketSize
+	0x00,				// bInterval
+
+	// string descriptors
+	0x04,
+	DESC_STRING,
+	LE_WORD(0x0409),
+
+	0x0E,
+	DESC_STRING,
+	'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
+
+	0x14,
+	DESC_STRING,
+	'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
+
+	0x12,
+	DESC_STRING,
+	'A', 0, 'B', 0, 'S', 0, 'M', 0, 'o', 0, 't', 0, 'o', 0, 'r', 0,
+
+// terminating zero
+	0
+};
+
+
+/**
+	Local function to handle incoming bulk data
+
+	@param [in] bEP
+	@param [in] bEPStatus
+ */
+static void BulkOut(unsigned char bEP, unsigned char bEPStatus)
+{
+	int i, iLen;
+	long lHigherPriorityTaskWoken = pdFALSE;
+
+	(void) bEPStatus;
+
+	// get data from USB into intermediate buffer
+	iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
+	for (i = 0; i < iLen; i++) {
+		// put into queue
+		xQueueSendFromISR(xRxedChars, &(abBulkBuf[ i ]), &lHigherPriorityTaskWoken);
+	}
+
+	portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+}
+
+
+/**
+	Local function to handle outgoing bulk data
+
+	@param [in] bEP
+	@param [in] bEPStatus
+ */
+static void BulkIn(unsigned char bEP, unsigned char bEPStatus)
+{
+	int i, iLen;
+	long lHigherPriorityTaskWoken = pdFALSE;
+
+	(void) bEPStatus;
+
+	if (uxQueueMessagesWaitingFromISR(xCharsForTx) == 0) {
+		// no more data, disable further NAK interrupts until next USB frame
+		USBHwNakIntEnable(0);
+		return;
+	}
+
+	// get bytes from transmit FIFO into intermediate buffer
+	for (i = 0; i < MAX_PACKET_SIZE; i++) {
+		if (xQueueReceiveFromISR(xCharsForTx, (&abBulkBuf[i]), &lHigherPriorityTaskWoken) != pdPASS) {
+			break;
+		}
+	}
+	iLen = i;
+
+	// send over USB
+	if (iLen > 0) {
+		USBHwEPWrite(bEP, abBulkBuf, iLen);
+	}
+
+	portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+}
+
+
+/**
+	Local function to handle the USB-CDC class requests
+
+	@param [in] pSetup
+	@param [out] piLen
+	@param [out] ppbData
+ */
+static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
+{
+	switch (pSetup->bRequest) {
+
+		// set line coding
+	case SET_LINE_CODING:
+		DBG("SET_LINE_CODING\n");
+		memcpy((unsigned char *)&LineCoding, *ppbData, 7);
+		*piLen = 7;
+		DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",
+		    LineCoding.dwDTERate,
+		    LineCoding.bCharFormat,
+		    LineCoding.bParityType,
+		    LineCoding.bDataBits);
+		break;
+
+		// get line coding
+	case GET_LINE_CODING:
+		DBG("GET_LINE_CODING\n");
+		*ppbData = (unsigned char *) & LineCoding;
+		*piLen = 7;
+		break;
+
+		// set control line state
+	case SET_CONTROL_LINE_STATE:
+		// bit0 = DTR, bit = RTS
+		DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);
+		break;
+
+	default:
+		return FALSE;
+	}
+	return TRUE;
+}
+
+
+/**
+	Writes one character to VCOM port
+
+	@param [in] c character to write
+	@returns character written, or EOF if character could not be written
+ */
+int VCOM_putchar(int c)
+{
+	char cc = (char) c;
+
+	if (xQueueSend(xCharsForTx, &cc, usbMAX_SEND_BLOCK) == pdPASS) {
+		return c;
+	} else {
+		return EOF;
+	}
+}
+
+
+/**
+	Reads one character from VCOM port
+
+	@returns character read, or EOF if character could not be read
+ */
+int VCOM_getchar(void)
+{
+	unsigned char c;
+
+	/* Block the task until a character is available. */
+	xQueueReceive(xRxedChars, &c, portMAX_DELAY);
+	return c;
+}
+
+
+/**
+	Interrupt handler
+
+	Simply calls the USB ISR
+ */
+void USB_IRQHandler(void)
+{
+	USBHwISR();
+}
+
+
+static void USBFrameHandler(unsigned short wFrame)
+{
+	(void) wFrame;
+
+	if (uxQueueMessagesWaitingFromISR(xCharsForTx) > 0) {
+		// data available, enable NAK interrupt on bulk in
+		USBHwNakIntEnable(INACK_BI);
+	}
+}
+
+unsigned long CPUcpsie(void)
+{
+	unsigned long ulRet;
+
+	//
+	// Read PRIMASK and enable interrupts.
+	//
+	__asm("    mrs     %0, PRIMASK\n"
+	      "    cpsie   i\n"
+	      "    bx      lr\n"
+      : "=r"(ulRet));
+
+	//
+	// The return is handled in the inline assembly, but the compiler will
+	// still complain if there is not an explicit return here (despite the fact
+	// that this does not result in any code being produced because of the
+	// naked attribute).
+	//
+	return(ulRet);
+}
+
+void vUSBTask(void *pvParameters)
+{
+	//int c;
+	portTickType xLastFlashTime;
+
+	/* Just to prevent compiler warnings about the unused parameter. */
+	(void) pvParameters;
+	DBG("Initialising USB stack\n");
+
+	xRxedChars = xQueueCreate(usbRXBUFFER_LEN, sizeof(char));
+	xCharsForTx = xQueueCreate(usbTXBUFFER_LEN, sizeof(char));
+
+	if ((xRxedChars == NULL) || (xCharsForTx == NULL)) {
+		/* Not enough heap available to create the buffer queues, can't do
+		anything so just delete ourselves. */
+		vTaskDelete(NULL);
+	}
+
+
+	// initialise stack
+	USBInit();
+
+	// register descriptors
+	USBRegisterDescriptors(abDescriptors);
+
+	// register class request handler
+	USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData);
+
+	// register endpoint handlers
+	USBHwRegisterEPIntHandler(INT_IN_EP, NULL);
+	USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn);
+	USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut);
+
+	// register frame handler
+	USBHwRegisterFrameHandler(USBFrameHandler);
+
+	// enable bulk-in interrupts on NAKs
+	USBHwNakIntEnable(INACK_BI);
+
+	DBG("Starting USB communication\n");
+
+	NVIC_SetPriority(USB_IRQn, configUSB_INTERRUPT_PRIORITY);
+	NVIC_EnableIRQ(USB_IRQn);
+
+	// connect to bus
+
+	DBG("Connecting to USB bus\n");
+	USBHwConnect(TRUE);
+	
+	xLastFlashTime = xTaskGetTickCount();
+	
+	// echo any character received (do USB stuff in interrupt)
+	for (;;) {
+	//	c = VCOM_getchar();
+	//	if (c != EOF) {
+	//		// Echo character back with INCREMENT_ECHO_BY offset, so for example if
+	//		// INCREMENT_ECHO_BY is 1 and 'A' is received, 'B' will be echoed back.
+	//		VCOM_putchar(c + INCREMENT_ECHO_BY);
+	//	}
+		vTaskDelayUntil(&xLastFlashTime, 1000 / portTICK_RATE_MS);
+	}
+}
+
diff --git a/gyro_board/src/usb/LPCUSB/USB_SENSOR_STREAM.c b/gyro_board/src/usb/LPCUSB/USB_SENSOR_STREAM.c
new file mode 100644
index 0000000..af1eede
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/USB_SENSOR_STREAM.c
@@ -0,0 +1,355 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "task.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "usbapi.h"
+#include "usbdebug.h"
+#include "usbstruct.h"
+
+#include "LPC17xx.h"
+
+#define usbMAX_SEND_BLOCK		( 20 / portTICK_RATE_MS )
+#define usbRXBUFFER_LEN			( 80 )
+#define usbTXBUFFER_LEN			( 600 )
+
+#define INT_IN_EP		0x81 //read manual for picking these...
+#define INT_OUT_EP		0x04
+#define BULK_IN_EP		0x82
+#define BULK_OUT_EP		0x05
+
+#define MAX_PACKET_SIZE	64
+
+#define LE_WORD(x)		((x)&0xFF),((x)>>8)
+
+static xQueueHandle xRxedChars = NULL, xCharsForTx = NULL;
+
+static const unsigned char abDescriptors[] = {
+
+// device descriptor
+	0x12,
+	DESC_DEVICE,
+	LE_WORD(0x0101),		// bcdUSB
+	0xFF,				// bDeviceClass
+	0x00,				// bDeviceSubClass
+	0x00,				// bDeviceProtocol
+	MAX_PACKET_SIZE0,		// bMaxPacketSize
+	LE_WORD(0x1424),		// idVendor
+	LE_WORD(0xd243),		// idProduct
+	LE_WORD(0x0153),		// bcdDevice
+	0x03,				// iManufacturer
+	0x36,				// iProduct
+	0x33,				// iSerialNumber
+	0x01,				// bNumConfigurations
+
+// configuration descriptor
+	0x09,
+	DESC_CONFIGURATION,
+	LE_WORD(67),			// wTotalLength
+	0x01,				// bNumInterfaces
+	0x01,				// bConfigurationValue
+	0x00,				// iConfiguration
+	0xC0,				// bmAttributes
+	0x32,				// bMaxPower
+// data class interface descriptor
+	0x09,
+	DESC_INTERFACE,
+	0x00,				// bInterfaceNumber
+	0x00,				// bAlternateSetting
+	0x04,				// bNumEndPoints
+	0x0A,				// bInterfaceClass = data
+	0x00,				// bInterfaceSubClass
+	0x00,				// bInterfaceProtocol
+	0x00,				// iInterface
+// debug EP OUT
+	0x07,
+	DESC_ENDPOINT,
+	BULK_OUT_EP,			// bEndpointAddress
+	0x02,				// bmAttributes = bulk
+	LE_WORD(MAX_PACKET_SIZE),	// wMaxPacketSize
+	0x00,				// bInterval
+// debug EP in
+	0x07,
+	DESC_ENDPOINT,
+	BULK_IN_EP,			// bEndpointAddress
+	0x02,				// bmAttributes = bulk
+	LE_WORD(MAX_PACKET_SIZE),	// wMaxPacketSize
+	0x00,				// bInterval
+// data EP OUT
+	0x07,
+	DESC_ENDPOINT,
+	INT_OUT_EP,			// bEndpointAddress
+	0x03,				// bmAttributes = intr
+	LE_WORD(MAX_PACKET_SIZE),	// wMaxPacketSize
+	0x01,				// bInterval
+// data EP in
+	0x07,
+	DESC_ENDPOINT,
+	INT_IN_EP,			// bEndpointAddress
+	0x03,				// bmAttributes = intr
+	LE_WORD(MAX_PACKET_SIZE),	// wMaxPacketSize
+	0x01,				// bInterval
+
+	// string descriptors
+	0x04,
+	DESC_STRING,
+	LE_WORD(0x0409),
+
+	0x0E,
+	DESC_STRING,
+	'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
+
+	0x14,
+	DESC_STRING,
+	'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
+
+	0x12,
+	DESC_STRING,
+	'A', 0, 'B', 0, 'S', 0, 'M', 0, 'o', 0, 't', 0, 'o', 0, 'r', 0,
+
+// terminating zero
+	0
+};
+
+
+/**
+ * Local function to handle incoming bulk data
+ *
+ * @param [in] bEP
+ * @param [in] bEPStatus
+ */
+static void DebugOut(unsigned char bEP, unsigned char bEPStatus) {
+  int i, iLen;
+  long lHigherPriorityTaskWoken = pdFALSE;
+  unsigned char abBulkBuf[64];
+
+  (void) bEPStatus;
+
+  // get data from USB into intermediate buffer
+  iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
+  for (i = 0; i < iLen; i++) {
+    // put into queue
+    xQueueSendFromISR(xRxedChars, &(abBulkBuf[ i ]), &lHigherPriorityTaskWoken);
+  }
+
+  portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+}
+
+
+/**
+ * Local function to handle outgoing bulk data
+ *
+ * @param [in] bEP
+ * @param [in] bEPStatus
+ */
+static void DebugIn(unsigned char bEP, unsigned char bEPStatus) {
+  int i, iLen;
+  long lHigherPriorityTaskWoken = pdFALSE;
+  unsigned char abBulkBuf[64];
+
+  (void) bEPStatus;
+
+  if (uxQueueMessagesWaitingFromISR(xCharsForTx) == 0) {
+    // no more data, disable further NAK interrupts until next USB frame
+    USBHwNakIntEnable(INACK_II);
+    return;
+  }
+
+  // get bytes from transmit FIFO into intermediate buffer
+  for (i = 0; i < MAX_PACKET_SIZE; i++) {
+    if (xQueueReceiveFromISR(xCharsForTx, (&abBulkBuf[i]),
+                             &lHigherPriorityTaskWoken) != pdPASS) {
+      break;
+    }
+  }
+  iLen = i;
+
+  // send over USB
+  if (iLen > 0) {
+    USBHwEPWrite(bEP, abBulkBuf, iLen);
+  }
+
+  portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+}
+
+extern int64_t gyro_angle;
+static unsigned char abDataBuf[64];
+int VCOM_putcharFromISR(int c, long *woken);
+static void DataOut(unsigned char bEP, unsigned char bEPStatus) {
+  int iLen;
+  long lHigherPriorityTaskWoken = pdFALSE;
+  char *a = "hello\n";
+  while(*a){
+    VCOM_putcharFromISR(*a,&lHigherPriorityTaskWoken);
+    a ++;
+  }
+  iLen = USBHwEPRead(bEP, abDataBuf, sizeof(abDataBuf));
+  portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+}
+static void DataIn(unsigned char bEP, unsigned char bEPStatus) {
+  long lHigherPriorityTaskWoken = pdFALSE;
+  unsigned char buff[16];
+  memcpy(buff, &gyro_angle, sizeof(gyro_angle));
+  USBHwEPWrite(bEP, buff, sizeof(gyro_angle));
+  portEND_SWITCHING_ISR(lHigherPriorityTaskWoken);
+}
+
+/**
+ * Writes one character to VCOM port
+ *
+ * @param [in] c character to write
+ * @returns character written, or EOF if character could not be written
+ */
+int VCOM_putcharFromISR(int c, long *lHigherPriorityTaskWoken) {
+  char cc = (char) c;
+
+  if (xQueueSendFromISR(xCharsForTx, &cc,
+                        lHigherPriorityTaskWoken) == pdPASS) {
+    return c;
+  } else {
+    return EOF;
+  }
+}
+
+int VCOM_putchar(int c) {
+  char cc = (char) c;
+
+  // Don't block if not connected to USB.
+  if (xQueueSend(xCharsForTx, &cc,
+                 USBIsConnected() ? usbMAX_SEND_BLOCK : 0) == pdPASS) {
+    return c;
+  } else {
+    return EOF;
+  }
+}
+
+
+/**
+ * Reads one character from VCOM port
+ *
+ * @returns character read, or EOF if character could not be read
+ */
+int VCOM_getchar(void) {
+  unsigned char c;
+
+  /* Block the task until a character is available. */
+  if(xQueueReceive(xRxedChars, &c, 0) == pdTRUE){  //portMAX_DELAY);
+    return c;
+  }
+  return -1;
+}
+
+
+/**
+ * Interrupt handler
+ *
+ * Simply calls the USB ISR
+ */
+void USB_IRQHandler(void) {
+	USBHwISR();
+}
+
+
+static void USBFrameHandler(unsigned short wFrame) {
+  (void) wFrame;
+
+	if (uxQueueMessagesWaitingFromISR(xCharsForTx) > 0) {
+		// data available, enable NAK interrupt on bulk in
+		USBHwNakIntEnable(INACK_BI);
+	}
+}
+
+void vUSBTask(void *pvParameters) {
+  portTickType xLastFlashTime;
+
+  /* Just to prevent compiler warnings about the unused parameter. */
+  (void) pvParameters;
+  DBG("Initialising USB stack\n");
+
+  xRxedChars = xQueueCreate(usbRXBUFFER_LEN, sizeof(char));
+  xCharsForTx = xQueueCreate(usbTXBUFFER_LEN, sizeof(char));
+
+  if ((xRxedChars == NULL) || (xCharsForTx == NULL)) {
+    /* Not enough heap available to create the buffer queues, can't do
+       anything so just delete ourselves. */
+    vTaskDelete(NULL);
+  }
+
+  // initialise stack
+  USBInit();
+
+  // register descriptors
+  USBRegisterDescriptors(abDescriptors);
+
+  // register class request handler
+  //USBRegisterRequestHandler(REQTYPE_TYPE_CLASS,
+  //                          HandleClassRequest, abClassReqData);
+
+  // register endpoint handlers
+  USBHwRegisterEPIntHandler(INT_IN_EP, DataIn);
+  USBHwRegisterEPIntHandler(INT_OUT_EP, DataOut);
+  USBHwRegisterEPIntHandler(BULK_IN_EP, DebugIn);
+  USBHwRegisterEPIntHandler(BULK_OUT_EP, DebugOut);
+
+  // register frame handler
+  USBHwRegisterFrameHandler(USBFrameHandler);
+
+  // enable bulk-in interrupts on NAKs
+  USBHwNakIntEnable(INACK_BI);
+
+  DBG("Starting USB communication\n");
+
+  NVIC_SetPriority(USB_IRQn, configUSB_INTERRUPT_PRIORITY);
+  NVIC_EnableIRQ(USB_IRQn);
+
+  // connect to bus
+
+  DBG("Connecting to USB bus\n");
+  USBHwConnect(TRUE);
+
+  xLastFlashTime = xTaskGetTickCount();
+
+  vTaskDelayUntil(&xLastFlashTime, 1000 / portTICK_RATE_MS * 100);
+
+  //USBHwAllowConnect();
+  // echo any character received (do USB stuff in interrupt)
+  for (;;) {
+    //	c = VCOM_getchar();
+    //	if (c != EOF) {
+    //		// Echo character back with INCREMENT_ECHO_BY offset, so for example if
+    //		// INCREMENT_ECHO_BY is 1 and 'A' is received, 'B' will be echoed back.
+    //		VCOM_putchar(c + INCREMENT_ECHO_BY);
+    //	}
+    vTaskDelayUntil(&xLastFlashTime, 1000 / portTICK_RATE_MS);
+  }
+}
+
diff --git a/gyro_board/src/usb/LPCUSB/type.h b/gyro_board/src/usb/LPCUSB/type.h
new file mode 100644
index 0000000..0727519
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/type.h
@@ -0,0 +1,38 @@
+/*****************************************************************************
+ *   type.h:  Type definition Header file for NXP LPC17xx Family
+ *   Microprocessors
+ *
+ *   Copyright(C) 2008, NXP Semiconductor
+ *   All rights reserved.
+ *
+ *   History
+ *   2008.08.21  ver 1.00    Prelimnary version, first Release
+ *
+******************************************************************************/
+#ifndef __TYPE_H__
+#define __TYPE_H__
+
+#ifndef NULL
+#define NULL    ((void *)0)
+#endif
+
+#ifndef FALSE
+#define FALSE   (0)
+#endif
+
+#ifndef TRUE
+#define TRUE    (1)
+#endif
+
+typedef unsigned char  BYTE;
+typedef unsigned short WORD;
+typedef unsigned long  DWORD;
+typedef unsigned int   BOOL;
+
+typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
+typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
+
+/* Pointer to Function returning Void (any number of parameters) */
+typedef void (*PFV)();
+
+#endif  /* __TYPE_H__ */
diff --git a/gyro_board/src/usb/LPCUSB/usbapi.h b/gyro_board/src/usb/LPCUSB/usbapi.h
new file mode 100644
index 0000000..e1fade8
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/usbapi.h
@@ -0,0 +1,125 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+	@file
+*/
+
+#include "usbstruct.h"		// for TSetupPacket
+
+/*************************************************************************
+	USB configuration
+**************************************************************************/
+
+#define MAX_PACKET_SIZE0	64		/**< maximum packet size for EP 0 */
+
+/*************************************************************************
+	USB hardware interface
+**************************************************************************/
+
+// endpoint status sent through callback
+#define EP_STATUS_DATA		(1<<0)		/**< EP has data */
+#define EP_STATUS_STALLED	(1<<1)		/**< EP is stalled */
+#define EP_STATUS_SETUP		(1<<2)		/**< EP received setup packet */
+#define EP_STATUS_ERROR		(1<<3)		/**< EP data was overwritten by setup packet */
+#define EP_STATUS_NACKED	(1<<4)		/**< EP sent NAK */
+
+// device status sent through callback
+#define DEV_STATUS_CONNECT		(1<<0)	/**< device just got connected */
+#define DEV_STATUS_SUSPEND		(1<<2)	/**< device entered suspend state */
+#define DEV_STATUS_RESET		(1<<4)	/**< device just got reset */
+
+// interrupt bits for NACK events in USBHwNakIntEnable
+// (these bits conveniently coincide with the LPC176x USB controller bit)
+#define INACK_CI		(1<<1)			/**< interrupt on NACK for control in */
+#define INACK_CO		(1<<2)			/**< interrupt on NACK for control out */
+#define INACK_II		(1<<3)			/**< interrupt on NACK for interrupt in */
+#define INACK_IO		(1<<4)			/**< interrupt on NACK for interrupt out */
+#define INACK_BI		(1<<5)			/**< interrupt on NACK for bulk in */
+#define INACK_BO		(1<<6)			/**< interrupt on NACK for bulk out */
+
+BOOL USBHwInit(void);
+void USBHwISR(void);
+
+void USBHwNakIntEnable(unsigned char bIntBits);
+
+void USBHwConnect(BOOL fConnect);
+int USBIsConnected(void);
+
+void USBHwSetAddress(unsigned char bAddr);
+void USBHwConfigDevice(BOOL fConfigured);
+
+// endpoint operations
+void USBHwEPConfig(unsigned char bEP, unsigned short wMaxPacketSize);
+int  USBHwEPRead(unsigned char bEP, unsigned char *pbBuf, int iMaxLen);
+int	 USBHwEPWrite(unsigned char bEP, unsigned char *pbBuf, int iLen);
+void USBHwEPStall(unsigned char bEP, BOOL fStall);
+unsigned char   USBHwEPGetStatus(unsigned char bEP);
+
+/** Endpoint interrupt handler callback */
+typedef void (TFnEPIntHandler)(unsigned char bEP, unsigned char bEPStatus);
+void USBHwRegisterEPIntHandler(unsigned char bEP, TFnEPIntHandler *pfnHandler);
+
+/** Device status handler callback */
+typedef void (TFnDevIntHandler)(unsigned char bDevStatus);
+void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler);
+
+/** Frame event handler callback */
+typedef void (TFnFrameHandler)(unsigned short wFrame);
+void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler);
+
+/** Configuration event handler callback */
+typedef void (SetConfigHandler)(void);
+void USBHwRegisterSetConfigHandler(SetConfigHandler *handler);
+
+
+/*************************************************************************
+	USB application interface
+**************************************************************************/
+
+// initialise the complete stack, including HW
+BOOL USBInit(void);
+
+/** Request handler callback (standard, vendor, class) */
+typedef BOOL (TFnHandleRequest)(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData);
+void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore);
+void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler);
+
+/** Descriptor handler callback */
+typedef BOOL (TFnGetDescriptor)(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData);
+
+/** Default standard request handler */
+BOOL USBHandleStandardRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData);
+
+/** Default EP0 handler */
+void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat);
+
+/** Descriptor handling */
+void USBRegisterDescriptors(const unsigned char *pabDescriptors);
+BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData);
+
+void USBHwAllowConnect(void);
diff --git a/gyro_board/src/usb/LPCUSB/usbcontrol.c b/gyro_board/src/usb/LPCUSB/usbcontrol.c
new file mode 100644
index 0000000..e02f492
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/usbcontrol.c
@@ -0,0 +1,236 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+	Control transfer handler.
+
+	This module handles control transfers and is normally installed on the
+	endpoint 0 callback.
+
+	Control transfers can be of the following type:
+	0 Standard;
+	1 Class;
+	2 Vendor;
+	3 Reserved.
+
+	A callback can be installed for each of these control transfers using
+	USBRegisterRequestHandler.
+	When an OUT request arrives, data is collected in the data store provided
+	with the USBRegisterRequestHandler call. When the transfer is done, the
+	callback is called.
+	When an IN request arrives, the callback is called immediately to either
+	put the control transfer data in the data store, or to get a pointer to
+	control transfer data. The data is then packetised and sent to the host.
+*/
+
+#include "usbdebug.h"
+
+#include "usbstruct.h"
+#include "usbapi.h"
+
+
+
+#define	MAX_CONTROL_SIZE	128	/**< maximum total size of control transfer data */
+#define	MAX_REQ_HANDLERS	4	/**< standard, class, vendor, reserved */
+
+static TSetupPacket		Setup;	/**< setup packet */
+
+static unsigned char				*pbData;	/**< pointer to data buffer */
+static int				iResidue;	/**< remaining bytes in buffer */
+static int				iLen;		/**< total length of control transfer */
+
+/** Array of installed request handler callbacks */
+static TFnHandleRequest *apfnReqHandlers[4] = {NULL, NULL, NULL, NULL};
+/** Array of installed request data pointers */
+static unsigned char				*apbDataStore[4] = {NULL, NULL, NULL, NULL};
+
+/**
+	Local function to handle a request by calling one of the installed
+	request handlers.
+
+	In case of data going from host to device, the data is at *ppbData.
+	In case of data going from device to host, the handler can either
+	choose to write its data at *ppbData or update the data pointer.
+
+	@param [in]		pSetup		The setup packet
+	@param [in,out]	*piLen		Pointer to data length
+	@param [in,out]	ppbData		Data buffer.
+
+	@return TRUE if the request was handles successfully
+ */
+static BOOL _HandleRequest(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
+{
+	TFnHandleRequest *pfnHandler;
+	int iType;
+
+	iType = REQTYPE_GET_TYPE(pSetup->bmRequestType);
+	pfnHandler = apfnReqHandlers[iType];
+	if (pfnHandler == NULL) {
+		DBG("No handler for reqtype %d\n", iType);
+		return FALSE;
+	}
+
+	return pfnHandler(pSetup, piLen, ppbData);
+}
+
+
+/**
+	Local function to stall the control endpoint
+
+	@param [in]	bEPStat	Endpoint status
+ */
+static void StallControlPipe(unsigned char bEPStat)
+{
+	unsigned char	*pb;
+	int	i;
+
+	USBHwEPStall(0x80, TRUE);
+
+// dump setup packet
+	DBG("STALL on [");
+	pb = (unsigned char *) & Setup;
+	for (i = 0; i < 8; i++) {
+		DBG(" %02x", *pb++);
+	}
+	DBG("] stat=%x\n", bEPStat);
+}
+
+
+/**
+	Sends next chunk of data (possibly 0 bytes) to host
+ */
+static void DataIn(void)
+{
+	int iChunk;
+
+	if (MAX_PACKET_SIZE0 < iResidue) {
+		iChunk = MAX_PACKET_SIZE0;
+	} else {
+		iChunk = iResidue;
+	}
+
+	USBHwEPWrite(0x80, pbData, iChunk);
+	pbData += iChunk;
+	iResidue -= iChunk;
+}
+
+
+/**
+ *	Handles IN/OUT transfers on EP0
+ *
+ *	@param [in]	bEP		Endpoint address
+ *	@param [in]	bEPStat	Endpoint status
+ */
+void USBHandleControlTransfer(unsigned char bEP, unsigned char bEPStat)
+{
+	int iChunk, iType;
+
+	if (bEP == 0x00) {
+		// OUT transfer
+		if (bEPStat & EP_STATUS_SETUP) {
+			// setup packet, reset request message state machine
+			USBHwEPRead(0x00, (unsigned char *)&Setup, sizeof(Setup));
+			DBG("S%x", Setup.bRequest);
+
+			// defaults for data pointer and residue
+			iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
+			pbData = apbDataStore[iType];
+			iResidue = Setup.wLength;
+			iLen = Setup.wLength;
+
+			if ((Setup.wLength == 0) ||
+			                (REQTYPE_GET_DIR(Setup.bmRequestType) == REQTYPE_DIR_TO_HOST)) {
+				// ask installed handler to process request
+				if (!_HandleRequest(&Setup, &iLen, &pbData)) {
+					DBG("_HandleRequest1 failed\n");
+					StallControlPipe(bEPStat);
+					return;
+				}
+				// send smallest of requested and offered length
+				if (iLen < Setup.wLength) {
+					iResidue = iLen;
+				} else {
+					iResidue = Setup.wLength;
+				}
+
+				// send first part (possibly a zero-length status message)
+				DataIn();
+			}
+		} else {
+			if (iResidue > 0) {
+				// store data
+				iChunk = USBHwEPRead(0x00, pbData, iResidue);
+				if (iChunk < 0) {
+					StallControlPipe(bEPStat);
+					return;
+				}
+				pbData += iChunk;
+				iResidue -= iChunk;
+				if (iResidue == 0) {
+					// received all, send data to handler
+					iType = REQTYPE_GET_TYPE(Setup.bmRequestType);
+					pbData = apbDataStore[iType];
+					if (!_HandleRequest(&Setup, &iLen, &pbData)) {
+						DBG("_HandleRequest2 failed\n");
+						StallControlPipe(bEPStat);
+						return;
+					}
+					// send status to host
+					DataIn();
+				}
+			} else {
+				// absorb zero-length status message
+				iChunk = USBHwEPRead(0x00, NULL, 0);
+				DBG(iChunk > 0 ? "?" : "");
+			}
+		}
+	} else if (bEP == 0x80) {
+		// IN transfer
+		// send more data if available (possibly a 0-length packet)
+		DataIn();
+	} else {
+		ASSERT(FALSE);
+	}
+}
+
+
+/**
+	Registers a callback for handling requests
+
+	@param [in]	iType			Type of request, e.g. REQTYPE_TYPE_STANDARD
+	@param [in]	*pfnHandler		Callback function pointer
+	@param [in]	*pbDataStore	Data storage area for this type of request
+ */
+void USBRegisterRequestHandler(int iType, TFnHandleRequest *pfnHandler, unsigned char *pbDataStore)
+{
+	ASSERT(iType >= 0);
+	ASSERT(iType < 4);
+	apfnReqHandlers[iType] = pfnHandler;
+	apbDataStore[iType] = pbDataStore;
+}
+
diff --git a/gyro_board/src/usb/LPCUSB/usbdebug.h b/gyro_board/src/usb/LPCUSB/usbdebug.h
new file mode 100644
index 0000000..4b3d16b
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/usbdebug.h
@@ -0,0 +1,41 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// CodeRed - comment out this printf, as will use real one from stdio.h
+// to implement output via semihosting
+
+//int printf(const char *format, ...);
+# include <stdio.h>
+
+#ifdef _DEBUG
+#define DBG	printf
+#define ASSERT(x)	if(!(x)){DBG("\nAssertion '%s' failed in %s:%s#%d!\n",#x,__FILE__,__FUNCTION__,__LINE__);while(1);}
+#else
+#define DBG(x ...)
+#define ASSERT(x)
+#endif
+
diff --git a/gyro_board/src/usb/LPCUSB/usbhw_lpc.c b/gyro_board/src/usb/LPCUSB/usbhw_lpc.c
new file mode 100644
index 0000000..8229371
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/usbhw_lpc.c
@@ -0,0 +1,538 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+	USB hardware layer
+ */
+
+
+#include "usbdebug.h"
+#include "usbhw_lpc.h"
+#include "usbapi.h"
+
+#ifdef DEBUG
+// comment out the following line if you don't want to use debug LEDs
+//#define DEBUG_LED
+#endif
+
+/** Installed device interrupt handler */
+static TFnDevIntHandler *_pfnDevIntHandler = NULL;
+/** Installed endpoint interrupt handlers */
+static TFnEPIntHandler	*_apfnEPIntHandlers[16];
+/** Installed frame interrupt handlers */
+static TFnFrameHandler	*_pfnFrameHandler = NULL;
+
+/** convert from endpoint address to endpoint index */
+#define EP2IDX(bEP)	((((bEP)&0xF)<<1)|(((bEP)&0x80)>>7))
+/** convert from endpoint index to endpoint address */
+#define IDX2EP(idx)	((((idx)<<7)&0x80)|(((idx)>>1)&0xF))
+
+
+
+/**
+	Local function to wait for a device interrupt (and clear it)
+
+	@param [in]	dwIntr		Bitmask of interrupts to wait for
+ */
+static void Wait4DevInt(unsigned long dwIntr)
+{
+	// wait for specific interrupt
+	while ((USB->USBDevIntSt & dwIntr) != dwIntr);
+	// clear the interrupt bits
+	USB->USBDevIntClr = dwIntr;
+}
+
+
+/**
+	Local function to send a command to the USB protocol engine
+
+	@param [in]	bCmd		Command to send
+ */
+static void USBHwCmd(unsigned char bCmd)
+{
+	// clear CDFULL/CCEMTY
+	USB->USBDevIntClr = CDFULL | CCEMTY;
+	// write command code
+	USB->USBCmdCode = 0x00000500 | (bCmd << 16);
+	Wait4DevInt(CCEMTY);
+}
+
+
+/**
+	Local function to send a command + data to the USB protocol engine
+
+	@param [in]	bCmd		Command to send
+	@param [in]	bData		Data to send
+ */
+static void USBHwCmdWrite(unsigned char bCmd, unsigned short bData)
+{
+	// write command code
+	USBHwCmd(bCmd);
+
+	// write command data
+	USB->USBCmdCode = 0x00000100 | (bData << 16);
+	Wait4DevInt(CCEMTY);
+}
+
+
+/**
+	Local function to send a command to the USB protocol engine and read data
+
+	@param [in]	bCmd		Command to send
+
+	@return the data
+ */
+static unsigned char USBHwCmdRead(unsigned char bCmd)
+{
+	// write command code
+	USBHwCmd(bCmd);
+
+	// get data
+	USB->USBCmdCode = 0x00000200 | (bCmd << 16);
+	Wait4DevInt(CDFULL);
+	return USB->USBCmdData;
+}
+
+
+/**
+	'Realizes' an endpoint, meaning that buffer space is reserved for
+	it. An endpoint needs to be realised before it can be used.
+
+	From experiments, it appears that a USB reset causes USBReEP to
+	re-initialise to 3 (= just the control endpoints).
+	However, a USB bus reset does not disturb the USBMaxPSize settings.
+
+	@param [in]	idx			Endpoint index
+	@param [in] wMaxPSize	Maximum packet size for this endpoint
+ */
+static void USBHwEPRealize(int idx, unsigned short wMaxPSize)
+{
+	USB->USBReEP |= (1 << idx);
+	USB->USBEpInd = idx;
+	USB->USBMaxPSize = wMaxPSize;
+	Wait4DevInt(EP_RLZED);
+}
+
+
+/**
+	Enables or disables an endpoint
+
+	@param [in]	idx		Endpoint index
+	@param [in]	fEnable	TRUE to enable, FALSE to disable
+ */
+static void USBHwEPEnable(int idx, BOOL fEnable)
+{
+	USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fEnable ? 0 : EP_DA);
+}
+
+
+/**
+	Configures an endpoint and enables it
+
+	@param [in]	bEP				Endpoint number
+	@param [in]	wMaxPacketSize	Maximum packet size for this EP
+ */
+void USBHwEPConfig(unsigned char bEP, unsigned short wMaxPacketSize)
+{
+	int idx;
+
+	idx = EP2IDX(bEP);
+
+	// realise EP
+	USBHwEPRealize(idx, wMaxPacketSize);
+
+	// enable EP
+	USBHwEPEnable(idx, TRUE);
+}
+
+
+/**
+	Registers an endpoint event callback
+
+	@param [in]	bEP				Endpoint number
+	@param [in]	pfnHandler		Callback function
+ */
+void USBHwRegisterEPIntHandler(unsigned char bEP, TFnEPIntHandler *pfnHandler)
+{
+	int idx;
+
+	idx = EP2IDX(bEP);
+
+	ASSERT(idx < 32);
+
+	/* add handler to list of EP handlers */
+	_apfnEPIntHandlers[idx / 2] = pfnHandler;
+
+	/* enable EP interrupt */
+	USB->USBEpIntEn |= (1 << idx);
+	USB->USBDevIntEn |= EP_SLOW;
+
+	DBG("Registered handler for EP 0x%x\n", bEP);
+}
+
+
+/**
+	Registers an device status callback
+
+	@param [in]	pfnHandler	Callback function
+ */
+void USBHwRegisterDevIntHandler(TFnDevIntHandler *pfnHandler)
+{
+	_pfnDevIntHandler = pfnHandler;
+
+	// enable device interrupt
+	USB->USBDevIntEn |= DEV_STAT;
+
+	DBG("Registered handler for device status\n");
+}
+
+
+/**
+	Registers the frame callback
+
+	@param [in]	pfnHandler	Callback function
+ */
+void USBHwRegisterFrameHandler(TFnFrameHandler *pfnHandler)
+{
+	_pfnFrameHandler = pfnHandler;
+
+	// enable device interrupt
+	USB->USBDevIntEn |= FRAME;
+
+	DBG("Registered handler for frame\n");
+}
+
+
+/**
+	Sets the USB address.
+
+	@param [in]	bAddr		Device address to set
+ */
+void USBHwSetAddress(unsigned char bAddr)
+{
+	USBHwCmdWrite(CMD_DEV_SET_ADDRESS, DEV_EN | bAddr);
+}
+
+
+/**
+	Connects or disconnects from the USB bus
+
+	@param [in]	fConnect	If TRUE, connect, otherwise disconnect
+ */
+void USBHwConnect(BOOL fConnect)
+{
+	USBHwCmdWrite(CMD_DEV_STATUS, fConnect ? CON : 0);
+}
+
+int USBIsConnected(void) {
+  return (GPIO1->FIOPIN >> 18) & 0x1;
+}
+
+
+/**
+	Enables interrupt on NAK condition
+
+	For IN endpoints a NAK is generated when the host wants to read data
+	from the device, but none is available in the endpoint buffer.
+	For OUT endpoints a NAK is generated when the host wants to write data
+	to the device, but the endpoint buffer is still full.
+
+	The endpoint interrupt handlers can distinguish regular (ACK) interrupts
+	from NAK interrupt by checking the bits in their bEPStatus argument.
+
+	@param [in]	bIntBits	Bitmap indicating which NAK interrupts to enable
+ */
+void USBHwNakIntEnable(unsigned char bIntBits)
+{
+	USBHwCmdWrite(CMD_DEV_SET_MODE, bIntBits);
+}
+
+
+/**
+	Gets the status from a specific endpoint.
+
+	@param [in]	bEP		Endpoint number
+	@return Endpoint status byte (containing EP_STATUS_xxx bits)
+ */
+unsigned char	USBHwEPGetStatus(unsigned char bEP)
+{
+	int idx = EP2IDX(bEP);
+
+	return USBHwCmdRead(CMD_EP_SELECT | idx);
+}
+
+
+/**
+	Sets the stalled property of an endpoint
+
+	@param [in]	bEP		Endpoint number
+	@param [in]	fStall	TRUE to stall, FALSE to unstall
+ */
+void USBHwEPStall(unsigned char bEP, BOOL fStall)
+{
+	int idx = EP2IDX(bEP);
+
+	USBHwCmdWrite(CMD_EP_SET_STATUS | idx, fStall ? EP_ST : 0);
+}
+
+
+/**
+	Writes data to an endpoint buffer
+
+	@param [in]	bEP		Endpoint number
+	@param [in]	pbBuf	Endpoint data
+	@param [in]	iLen	Number of bytes to write
+
+	@return TRUE if the data was successfully written or <0 in case of error.
+*/
+int USBHwEPWrite(unsigned char bEP, unsigned char *pbBuf, int iLen)
+{
+	int idx;
+
+	idx = EP2IDX(bEP);
+
+	// set write enable for specific endpoint
+	USB->USBCtrl = WR_EN | ((bEP & 0xF) << 2);
+
+	// set packet length
+	USB->USBTxPLen = iLen;
+
+	// write data
+	while (USB->USBCtrl & WR_EN) {
+		USB->USBTxData = (pbBuf[3] << 24) | (pbBuf[2] << 16) | (pbBuf[1] << 8) | pbBuf[0];
+		pbBuf += 4;
+	}
+
+	// select endpoint and validate buffer
+	USBHwCmd(CMD_EP_SELECT | idx);
+	USBHwCmd(CMD_EP_VALIDATE_BUFFER);
+
+	return iLen;
+}
+
+
+/**
+	Reads data from an endpoint buffer
+
+	@param [in]	bEP		Endpoint number
+	@param [in]	pbBuf	Endpoint data
+	@param [in]	iMaxLen	Maximum number of bytes to read
+
+	@return the number of bytes available in the EP (possibly more than iMaxLen),
+	or <0 in case of error.
+ */
+int USBHwEPRead(unsigned char bEP, unsigned char *pbBuf, int iMaxLen)
+{
+	int i, idx;
+	unsigned long	dwData, dwLen;
+
+	idx = EP2IDX(bEP);
+
+	// set read enable bit for specific endpoint
+	USB->USBCtrl = RD_EN | ((bEP & 0xF) << 2);
+
+	// wait for PKT_RDY
+	do {
+		dwLen = USB->USBRxPLen;
+	} while ((dwLen & PKT_RDY) == 0);
+
+	// packet valid?
+	if ((dwLen & DV) == 0) {
+		return -1;
+	}
+
+	// get length
+	dwLen &= PKT_LNGTH_MASK;
+
+	// get data
+	dwData = 0;
+	for (i = 0; i < dwLen; i++) {
+		if ((i % 4) == 0) {
+			dwData = USB->USBRxData;
+		}
+		if ((pbBuf != NULL) && (i < iMaxLen)) {
+			pbBuf[i] = dwData & 0xFF;
+		}
+		dwData >>= 8;
+	}
+
+	// make sure RD_EN is clear
+	USB->USBCtrl = 0;
+
+	// select endpoint and clear buffer
+	USBHwCmd(CMD_EP_SELECT | idx);
+	USBHwCmd(CMD_EP_CLEAR_BUFFER);
+
+	return dwLen;
+}
+
+
+/**
+	Sets the 'configured' state.
+
+	All registered endpoints are 'realised' and enabled, and the
+	'configured' bit is set in the device status register.
+
+	@param [in]	fConfigured	If TRUE, configure device, else unconfigure
+ */
+void USBHwConfigDevice(BOOL fConfigured)
+{
+	// set configured bit
+	USBHwCmdWrite(CMD_DEV_CONFIG, fConfigured ? CONF_DEVICE : 0);
+}
+
+
+/**
+ * USB interrupt handler
+ *
+ * @todo Get all 11 bits of frame number instead of just 8
+ *
+ * Endpoint interrupts are mapped to the slow interrupt
+ */
+void USBHwISR(void) {
+	unsigned long dwStatus;
+	unsigned long dwIntBit;
+	unsigned char bEPStat, bDevStat, bStat;
+	int i;
+	unsigned short wFrame;
+
+	// handle device interrupts
+	dwStatus = USB->USBDevIntSt;
+
+	// frame interrupt
+	if (dwStatus & FRAME) {
+		// clear int
+		USB->USBDevIntClr = FRAME;
+		// call handler
+		if (_pfnFrameHandler != NULL) {
+			wFrame = USBHwCmdRead(CMD_DEV_READ_CUR_FRAME_NR);
+			_pfnFrameHandler(wFrame);
+		}
+	}
+
+	// device status interrupt
+	if (dwStatus & DEV_STAT) {
+		/*	Clear DEV_STAT interrupt before reading DEV_STAT register.
+			This prevents corrupted device status reads, see
+			LPC2148 User manual revision 2, 25 july 2006.
+		*/
+		USB->USBDevIntClr = DEV_STAT;
+		bDevStat = USBHwCmdRead(CMD_DEV_STATUS);
+		if (bDevStat & (CON_CH | SUS_CH | RST)) {
+			// convert device status into something HW independent
+			bStat = ((bDevStat & CON) ? DEV_STATUS_CONNECT : 0) |
+			        ((bDevStat & SUS) ? DEV_STATUS_SUSPEND : 0) |
+			        ((bDevStat & RST) ? DEV_STATUS_RESET : 0);
+			// call handler
+			if (_pfnDevIntHandler != NULL) {
+				_pfnDevIntHandler(bStat);
+			}
+		}
+	}
+
+	// endpoint interrupt
+	if (dwStatus & EP_SLOW) {
+		// clear EP_SLOW
+		USB->USBDevIntClr = EP_SLOW;
+		// check all endpoints
+		for (i = 0; i < 32; i++) {
+			dwIntBit = (1 << i);
+			if (USB->USBEpIntSt & dwIntBit) {
+				// clear int (and retrieve status)
+				USB->USBEpIntClr = dwIntBit;
+				Wait4DevInt(CDFULL);
+				bEPStat = USB->USBCmdData;
+				// convert EP pipe stat into something HW independent
+				bStat = ((bEPStat & EPSTAT_FE) ? EP_STATUS_DATA : 0) |
+				        ((bEPStat & EPSTAT_ST) ? EP_STATUS_STALLED : 0) |
+				        ((bEPStat & EPSTAT_STP) ? EP_STATUS_SETUP : 0) |
+				        ((bEPStat & EPSTAT_EPN) ? EP_STATUS_NACKED : 0) |
+				        ((bEPStat & EPSTAT_PO) ? EP_STATUS_ERROR : 0);
+				// call handler
+				if (_apfnEPIntHandlers[i / 2] != NULL) {
+					_apfnEPIntHandlers[i / 2](IDX2EP(i), bStat);
+				}
+			}
+		}
+	}
+}
+
+
+
+/**
+	Initialises the USB hardware
+
+
+	@return TRUE if the hardware was successfully initialised
+ */
+BOOL USBHwInit(void)
+{
+  // P2.9 -> USB_CONNECT
+  //PINCON->PINSEL4 &= ~0x000C0000;
+  //PINCON->PINSEL4 |= 0x00040000;
+  // Leave it disconnected.
+  // Before the device can be used, it needs to be connected.
+  GPIO2->FIODIR |= (1UL << 9UL);
+  GPIO2->FIOCLR = (1UL << 9UL);
+
+  // P1.18 -> USB_UP_LED
+  // P1.30 -> VBUS
+  PINCON->PINSEL3 &= ~0x30000030;
+  PINCON->PINSEL3 |= 0x00000010;
+
+  // P0.29 -> USB_D+
+  // P0.30 -> USB_D-
+  PINCON->PINSEL1 &= ~0x3C000000;
+  PINCON->PINSEL1 |= 0x14000000;
+
+  // enable PUSB
+  SC->PCONP |= (1 << 31);
+
+  USB->OTGClkCtrl = 0x12;	                  /* Dev clock, AHB clock enable  */
+  while ((USB->OTGClkSt & 0x12) != 0x12);
+
+  // disable/clear all interrupts for now
+  USB->USBDevIntEn = 0;
+  USB->USBDevIntClr = 0xFFFFFFFF;
+  USB->USBDevIntPri = 0;
+
+  USB->USBEpIntEn = 0;
+  USB->USBEpIntClr = 0xFFFFFFFF;
+  USB->USBEpIntPri = 0;
+
+  // by default, only ACKs generate interrupts
+  USBHwNakIntEnable(0);
+
+  return TRUE;
+}
+
+void USBHwAllowConnect(void)
+{
+	// Enable USB.
+        GPIO2->FIOSET = (1UL << 9UL);
+}
diff --git a/gyro_board/src/usb/LPCUSB/usbhw_lpc.h b/gyro_board/src/usb/LPCUSB/usbhw_lpc.h
new file mode 100644
index 0000000..d6b60af
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/usbhw_lpc.h
@@ -0,0 +1,149 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/**
+	Hardware definitions for the LPC176x USB controller
+
+	These are private to the usbhw module
+*/
+
+// CodeRed - pull in defines from NXP header file
+//#include "NXP\LPC17xx\LPC17xx.h"
+#include "LPC17xx.h"
+
+
+// CodeRed - these registers have been renamed on LPC176x
+#define USBReEP USBReEp
+#define OTG_CLK_CTRL USBClkCtrl
+#define OTG_CLK_STAT USBClkSt
+
+/* USBIntSt bits */
+#define USB_INT_REQ_LP				(1<<0)
+#define USB_INT_REQ_HP				(1<<1)
+#define USB_INT_REQ_DMA				(1<<2)
+#define USB_need_clock				(1<<8)
+#define EN_USB_BITS					(1<<31)
+
+/* USBDevInt... bits */
+#define FRAME						(1<<0)
+#define EP_FAST						(1<<1)
+#define EP_SLOW						(1<<2)
+#define DEV_STAT					(1<<3)
+#define CCEMTY						(1<<4)
+#define CDFULL						(1<<5)
+#define RxENDPKT					(1<<6)
+#define TxENDPKT					(1<<7)
+#define EP_RLZED					(1<<8)
+#define ERR_INT						(1<<9)
+
+/* USBRxPLen bits */
+#define PKT_LNGTH					(1<<0)
+#define PKT_LNGTH_MASK				0x3FF
+#define DV							(1<<10)
+#define PKT_RDY						(1<<11)
+
+/* USBCtrl bits */
+#define RD_EN						(1<<0)
+#define WR_EN						(1<<1)
+#define LOG_ENDPOINT				(1<<2)
+
+/* protocol engine command codes */
+/* device commands */
+#define CMD_DEV_SET_ADDRESS			0xD0
+#define CMD_DEV_CONFIG				0xD8
+#define CMD_DEV_SET_MODE			0xF3
+#define CMD_DEV_READ_CUR_FRAME_NR	0xF5
+#define CMD_DEV_READ_TEST_REG		0xFD
+#define CMD_DEV_STATUS				0xFE		/* read/write */
+#define CMD_DEV_GET_ERROR_CODE		0xFF
+#define CMD_DEV_READ_ERROR_STATUS	0xFB
+/* endpoint commands */
+#define CMD_EP_SELECT				0x00
+#define CMD_EP_SELECT_CLEAR			0x40
+#define CMD_EP_SET_STATUS			0x40
+#define CMD_EP_CLEAR_BUFFER			0xF2
+#define CMD_EP_VALIDATE_BUFFER		0xFA
+
+/* set address command */
+#define DEV_ADDR					(1<<0)
+#define DEV_EN						(1<<7)
+
+/* configure device command */
+#define CONF_DEVICE					(1<<0)
+
+/* set mode command */
+#define AP_CLK						(1<<0)
+#define INAK_CI						(1<<1)
+#define INAK_CO						(1<<2)
+#define INAK_II						(1<<3)
+#define INAK_IO						(1<<4)
+#define INAK_BI						(1<<5)
+#define INAK_BO						(1<<6)
+
+/* set get device status command */
+#define CON							(1<<0)
+#define CON_CH						(1<<1)
+#define SUS							(1<<2)
+#define SUS_CH						(1<<3)
+#define RST							(1<<4)
+
+/* get error code command */
+// ...
+
+/* Select Endpoint command read bits */
+#define EPSTAT_FE					(1<<0)
+#define EPSTAT_ST					(1<<1)
+#define EPSTAT_STP					(1<<2)
+#define EPSTAT_PO					(1<<3)
+#define EPSTAT_EPN					(1<<4)
+#define EPSTAT_B1FULL				(1<<5)
+#define EPSTAT_B2FULL				(1<<6)
+
+/* CMD_EP_SET_STATUS command */
+#define EP_ST						(1<<0)
+#define EP_DA						(1<<5)
+#define EP_RF_MO					(1<<6)
+#define EP_CND_ST					(1<<7)
+
+/* read error status command */
+#define PID_ERR						(1<<0)
+#define UEPKT						(1<<1)
+#define DCRC						(1<<2)
+#define TIMEOUT						(1<<3)
+#define EOP							(1<<4)
+#define B_OVRN						(1<<5)
+#define BTSTF						(1<<6)
+#define TGL_ERR						(1<<7)
+
+
+
+
+
+
+
+
diff --git a/gyro_board/src/usb/LPCUSB/usbinit.c b/gyro_board/src/usb/LPCUSB/usbinit.c
new file mode 100644
index 0000000..49b31a0
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/usbinit.c
@@ -0,0 +1,82 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+	USB stack initialisation
+ */
+
+
+#include "usbdebug.h"
+#include "usbapi.h"
+
+
+/** data storage area for standard requests */
+static unsigned char	abStdReqData[8];
+
+
+/**
+	USB reset handler
+
+	@param [in] bDevStatus	Device status
+ */
+static void HandleUsbReset(unsigned char bDevStatus)
+{
+	if (bDevStatus & DEV_STATUS_RESET) {
+		DBG("\n!");
+	}
+}
+
+
+/**
+	Initialises the USB hardware and sets up the USB stack by
+	installing default callbacks.
+
+	@return TRUE if initialisation was successful
+ */
+BOOL USBInit(void)
+{
+	// init hardware
+	USBHwInit();
+
+	// register bus reset handler
+	USBHwRegisterDevIntHandler(HandleUsbReset);
+
+	// register control transfer handler on EP0
+	USBHwRegisterEPIntHandler(0x00, USBHandleControlTransfer);
+	USBHwRegisterEPIntHandler(0x80, USBHandleControlTransfer);
+
+	// setup control endpoints
+	USBHwEPConfig(0x00, MAX_PACKET_SIZE0);
+	USBHwEPConfig(0x80, MAX_PACKET_SIZE0);
+
+	// register standard request handler
+	USBRegisterRequestHandler(REQTYPE_TYPE_STANDARD, USBHandleStandardRequest, abStdReqData);
+
+	return TRUE;
+}
+
diff --git a/gyro_board/src/usb/LPCUSB/usbstdreq.c b/gyro_board/src/usb/LPCUSB/usbstdreq.c
new file mode 100644
index 0000000..6a3fde5
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/usbstdreq.c
@@ -0,0 +1,438 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/** @file
+	Standard request handler.
+
+	This modules handles the 'chapter 9' processing, specifically the
+	standard device requests in table 9-3 from the universal serial bus
+	specification revision 2.0
+
+	Specific types of devices may specify additional requests (for example
+	HID devices add a GET_DESCRIPTOR request for interfaces), but they
+	will not be part of this module.
+
+	@todo some requests have to return a request error if device not configured:
+	@todo GET_INTERFACE, GET_STATUS, SET_INTERFACE, SYNCH_FRAME
+	@todo this applies to the following if endpoint != 0:
+	@todo SET_FEATURE, GET_FEATURE
+*/
+
+#include "usbdebug.h"
+#include "usbstruct.h"
+#include "usbapi.h"
+
+#define MAX_DESC_HANDLERS	4		/**< device, interface, endpoint, other */
+
+
+/* general descriptor field offsets */
+#define DESC_bLength					0	/**< length offset */
+#define DESC_bDescriptorType			1	/**< descriptor type offset */
+
+/* config descriptor field offsets */
+#define CONF_DESC_wTotalLength			2	/**< total length offset */
+#define CONF_DESC_bConfigurationValue	5	/**< configuration value offset */
+#define CONF_DESC_bmAttributes			7	/**< configuration characteristics */
+
+/* interface descriptor field offsets */
+#define INTF_DESC_bAlternateSetting		3	/**< alternate setting offset */
+
+/* endpoint descriptor field offsets */
+#define ENDP_DESC_bEndpointAddress		2	/**< endpoint address offset */
+#define ENDP_DESC_wMaxPacketSize		4	/**< maximum packet size offset */
+
+
+/** Currently selected configuration */
+static unsigned char				bConfiguration = 0;
+/** Installed custom request handler */
+static TFnHandleRequest	*pfnHandleCustomReq = NULL;
+/** Pointer to registered descriptors */
+static const unsigned char			*pabDescrip = NULL;
+
+
+/**
+	Registers a pointer to a descriptor block containing all descriptors
+	for the device.
+
+	@param [in]	pabDescriptors	The descriptor byte array
+ */
+void USBRegisterDescriptors(const unsigned char *pabDescriptors)
+{
+	pabDescrip = pabDescriptors;
+}
+
+
+/**
+	Parses the list of installed USB descriptors and attempts to find
+	the specified USB descriptor.
+
+	@param [in]		wTypeIndex	Type and index of the descriptor
+	@param [in]		wLangID		Language ID of the descriptor (currently unused)
+	@param [out]	*piLen		Descriptor length
+	@param [out]	*ppbData	Descriptor data
+
+	@return TRUE if the descriptor was found, FALSE otherwise
+ */
+BOOL USBGetDescriptor(unsigned short wTypeIndex, unsigned short wLangID, int *piLen, unsigned char **ppbData)
+{
+	unsigned char	bType, bIndex;
+	unsigned char	*pab;
+	int iCurIndex;
+
+	ASSERT(pabDescrip != NULL);
+
+	bType = GET_DESC_TYPE(wTypeIndex);
+	bIndex = GET_DESC_INDEX(wTypeIndex);
+
+	pab = (unsigned char *)pabDescrip;
+	iCurIndex = 0;
+
+	while (pab[DESC_bLength] != 0) {
+		if (pab[DESC_bDescriptorType] == bType) {
+			if (iCurIndex == bIndex) {
+				// set data pointer
+				*ppbData = pab;
+				// get length from structure
+				if (bType == DESC_CONFIGURATION) {
+					// configuration descriptor is an exception, length is at offset 2 and 3
+					*piLen =	(pab[CONF_DESC_wTotalLength]) |
+					         (pab[CONF_DESC_wTotalLength + 1] << 8);
+				} else {
+					// normally length is at offset 0
+					*piLen = pab[DESC_bLength];
+				}
+				return TRUE;
+			}
+			iCurIndex++;
+		}
+		// skip to next descriptor
+		pab += pab[DESC_bLength];
+	}
+	// nothing found
+	DBG("Desc %x not found!\n", wTypeIndex);
+	return FALSE;
+}
+
+
+/**
+	Configures the device according to the specified configuration index and
+	alternate setting by parsing the installed USB descriptor list.
+	A configuration index of 0 unconfigures the device.
+
+	@param [in]		bConfigIndex	Configuration index
+	@param [in]		bAltSetting		Alternate setting number
+
+	@todo function always returns TRUE, add stricter checking?
+
+	@return TRUE if successfully configured, FALSE otherwise
+ */
+static BOOL USBSetConfiguration(unsigned char bConfigIndex, unsigned char bAltSetting)
+{
+	unsigned char	*pab;
+	unsigned char	bCurConfig, bCurAltSetting;
+	unsigned char	bEP;
+	unsigned short	wMaxPktSize;
+
+	ASSERT(pabDescrip != NULL);
+
+	if (bConfigIndex == 0) {
+		// unconfigure device
+		USBHwConfigDevice(FALSE);
+	} else {
+		// configure endpoints for this configuration/altsetting
+		pab = (unsigned char *)pabDescrip;
+		bCurConfig = 0xFF;
+		bCurAltSetting = 0xFF;
+
+		while (pab[DESC_bLength] != 0) {
+
+			switch (pab[DESC_bDescriptorType]) {
+
+			case DESC_CONFIGURATION:
+				// remember current configuration index
+				bCurConfig = pab[CONF_DESC_bConfigurationValue];
+				break;
+
+			case DESC_INTERFACE:
+				// remember current alternate setting
+				bCurAltSetting = pab[INTF_DESC_bAlternateSetting];
+				break;
+
+			case DESC_ENDPOINT:
+				if ((bCurConfig == bConfigIndex) &&
+				                (bCurAltSetting == bAltSetting)) {
+					// endpoint found for desired config and alternate setting
+					bEP = pab[ENDP_DESC_bEndpointAddress];
+					wMaxPktSize =	(pab[ENDP_DESC_wMaxPacketSize]) |
+					              (pab[ENDP_DESC_wMaxPacketSize + 1] << 8);
+					// configure endpoint
+					USBHwEPConfig(bEP, wMaxPktSize);
+				}
+				break;
+
+			default:
+				break;
+			}
+			// skip to next descriptor
+			pab += pab[DESC_bLength];
+		}
+
+		// configure device
+		USBHwConfigDevice(TRUE);
+	}
+
+	return TRUE;
+}
+SetConfigHandler *SetConfig_CallBack = NULL;
+void USBHwRegisterSetConfigHandler(SetConfigHandler *handler){
+	SetConfig_CallBack = handler;
+}
+
+
+/**
+	Local function to handle a standard device request
+
+	@param [in]		pSetup		The setup packet
+	@param [in,out]	*piLen		Pointer to data length
+	@param [in,out]	ppbData		Data buffer.
+
+	@return TRUE if the request was handled successfully
+ */
+static BOOL HandleStdDeviceReq(TSetupPacket *pSetup, int *piLen, unsigned char **ppbData)
+{
+	unsigned char	*pbData = *ppbData;
+
+	switch (pSetup->bRequest) {
+
+	case REQ_GET_STATUS:
+		// bit 0: self-powered
+		// bit 1: remote wakeup = not supported
+		pbData[0] = 0;
+		pbData[1] = 0;
+		*piLen = 2;
+		break;
+
+	case REQ_SET_ADDRESS:
+		USBHwSetAddress(pSetup->wValue);
+		break;
+
+	case REQ_GET_DESCRIPTOR:
+		DBG("D%x", pSetup->wValue);
+		return USBGetDescriptor(pSetup->wValue, pSetup->wIndex, piLen, ppbData);
+
+	case REQ_GET_CONFIGURATION:
+		// indicate if we are configured
+		pbData[0] = bConfiguration;
+		*piLen = 1;
+		break;
+
+	case REQ_SET_CONFIGURATION:
+		if (!USBSetConfiguration(pSetup->wValue & 0xFF, 0)) {
+			DBG("USBSetConfiguration failed!\n");
+			return FALSE;
+		}
+		// configuration successful, update current configuration
+		bConfiguration = pSetup->wValue & 0xFF;
+		if(SetConfig_CallBack != NULL)
+			SetConfig_CallBack();
+		break;
+
+	case REQ_CLEAR_FEATURE:
+	case REQ_SET_FEATURE:
+		if (pSetup->wValue == FEA_REMOTE_WAKEUP) {
+			// put DEVICE_REMOTE_WAKEUP code here
+		}
+		if (pSetup->wValue == FEA_TEST_MODE) {
+			// put TEST_MODE code here
+		}
+		return FALSE;
+
+	case REQ_SET_DESCRIPTOR:
+		DBG("Device req %d not implemented\n", pSetup->bRequest);
+		return FALSE;
+
+	default:
+		DBG("Illegal device req %d\n", pSetup->bRequest);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+/**
+	Local function to handle a standard interface request
+
+	@param [in]		pSetup		The setup packet
+	@param [in,out]	*piLen		Pointer to data length
+	@param [in]		ppbData		Data buffer.
+
+	@return TRUE if the request was handled successfully
+ */
+static BOOL HandleStdInterfaceReq(TSetupPacket	*pSetup, int *piLen, unsigned char **ppbData)
+{
+	unsigned char	*pbData = *ppbData;
+
+	switch (pSetup->bRequest) {
+
+	case REQ_GET_STATUS:
+		// no bits specified
+		pbData[0] = 0;
+		pbData[1] = 0;
+		*piLen = 2;
+		break;
+
+	case REQ_CLEAR_FEATURE:
+	case REQ_SET_FEATURE:
+		// not defined for interface
+		return FALSE;
+
+	case REQ_GET_INTERFACE:	// TODO use bNumInterfaces
+		// there is only one interface, return n-1 (= 0)
+		pbData[0] = 0;
+		*piLen = 1;
+		break;
+
+	case REQ_SET_INTERFACE:	// TODO use bNumInterfaces
+		// there is only one interface (= 0)
+		if (pSetup->wValue != 0) {
+			return FALSE;
+		}
+		*piLen = 0;
+		break;
+
+	default:
+		DBG("Illegal interface req %d\n", pSetup->bRequest);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+/**
+	Local function to handle a standard endpoint request
+
+	@param [in]		pSetup		The setup packet
+	@param [in,out]	*piLen		Pointer to data length
+	@param [in]		ppbData		Data buffer.
+
+	@return TRUE if the request was handled successfully
+ */
+static BOOL HandleStdEndPointReq(TSetupPacket	*pSetup, int *piLen, unsigned char **ppbData)
+{
+	unsigned char	*pbData = *ppbData;
+
+	switch (pSetup->bRequest) {
+	case REQ_GET_STATUS:
+		// bit 0 = endpointed halted or not
+		pbData[0] = (USBHwEPGetStatus(pSetup->wIndex) & EP_STATUS_STALLED) ? 1 : 0;
+		pbData[1] = 0;
+		*piLen = 2;
+		break;
+
+	case REQ_CLEAR_FEATURE:
+		if (pSetup->wValue == FEA_ENDPOINT_HALT) {
+			// clear HALT by unstalling
+			USBHwEPStall(pSetup->wIndex, FALSE);
+			break;
+		}
+		// only ENDPOINT_HALT defined for endpoints
+		return FALSE;
+
+	case REQ_SET_FEATURE:
+		if (pSetup->wValue == FEA_ENDPOINT_HALT) {
+			// set HALT by stalling
+			USBHwEPStall(pSetup->wIndex, TRUE);
+			break;
+		}
+		// only ENDPOINT_HALT defined for endpoints
+		return FALSE;
+
+	case REQ_SYNCH_FRAME:
+		DBG("EP req %d not implemented\n", pSetup->bRequest);
+		return FALSE;
+
+	default:
+		DBG("Illegal EP req %d\n", pSetup->bRequest);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+/**
+	Default handler for standard ('chapter 9') requests
+
+	If a custom request handler was installed, this handler is called first.
+
+	@param [in]		pSetup		The setup packet
+	@param [in,out]	*piLen		Pointer to data length
+	@param [in]		ppbData		Data buffer.
+
+	@return TRUE if the request was handled successfully
+ */
+BOOL USBHandleStandardRequest(TSetupPacket	*pSetup, int *piLen, unsigned char **ppbData)
+{
+	// try the custom request handler first
+	if ((pfnHandleCustomReq != NULL) && pfnHandleCustomReq(pSetup, piLen, ppbData)) {
+		return TRUE;
+	}
+
+	switch (REQTYPE_GET_RECIP(pSetup->bmRequestType)) {
+	case REQTYPE_RECIP_DEVICE:
+		return HandleStdDeviceReq(pSetup, piLen, ppbData);
+	case REQTYPE_RECIP_INTERFACE:
+		return HandleStdInterfaceReq(pSetup, piLen, ppbData);
+	case REQTYPE_RECIP_ENDPOINT:
+		return HandleStdEndPointReq(pSetup, piLen, ppbData);
+	default:
+		return FALSE;
+	}
+}
+
+
+/**
+	Registers a callback for custom device requests
+
+	In USBHandleStandardRequest, the custom request handler gets a first
+	chance at handling the request before it is handed over to the 'chapter 9'
+	request handler.
+
+	This can be used for example in HID devices, where a REQ_GET_DESCRIPTOR
+	request is sent to an interface, which is not covered by the 'chapter 9'
+	specification.
+
+	@param [in]	pfnHandler	Callback function pointer
+ */
+void USBRegisterCustomReqHandler(TFnHandleRequest *pfnHandler)
+{
+	pfnHandleCustomReq = pfnHandler;
+}
+
diff --git a/gyro_board/src/usb/LPCUSB/usbstruct.h b/gyro_board/src/usb/LPCUSB/usbstruct.h
new file mode 100644
index 0000000..d6bd725
--- /dev/null
+++ b/gyro_board/src/usb/LPCUSB/usbstruct.h
@@ -0,0 +1,119 @@
+/*
+	LPCUSB, an USB device driver for LPC microcontrollers
+	Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl)
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/**
+	Definitions of structures of standard USB packets
+*/
+
+#ifndef _USBSTRUCT_H_
+#define _USBSTRUCT_H_
+
+// CodeRed - include the LPCUSB type.h file rather than NXP one directly
+#include "type.h"
+
+/** setup packet definitions */
+typedef struct {
+	unsigned char	bmRequestType;			/**< characteristics of the specific request */
+	unsigned char	bRequest;				/**< specific request */
+	unsigned short	wValue;					/**< request specific parameter */
+	unsigned short	wIndex;					/**< request specific parameter */
+	unsigned short	wLength;				/**< length of data transfered in data phase */
+} TSetupPacket;
+
+
+#define REQTYPE_GET_DIR(x)		(((x)>>7)&0x01)
+#define REQTYPE_GET_TYPE(x)		(((x)>>5)&0x03)
+#define REQTYPE_GET_RECIP(x)	((x)&0x1F)
+
+#define REQTYPE_DIR_TO_DEVICE	0
+#define REQTYPE_DIR_TO_HOST		1
+
+#define REQTYPE_TYPE_STANDARD	0
+#define REQTYPE_TYPE_CLASS		1
+#define REQTYPE_TYPE_VENDOR		2
+#define REQTYPE_TYPE_RESERVED	3
+
+#define REQTYPE_RECIP_DEVICE	0
+#define REQTYPE_RECIP_INTERFACE	1
+#define REQTYPE_RECIP_ENDPOINT	2
+#define REQTYPE_RECIP_OTHER		3
+
+/* standard requests */
+#define	REQ_GET_STATUS			0x00
+#define REQ_CLEAR_FEATURE		0x01
+#define REQ_SET_FEATURE			0x03
+#define REQ_SET_ADDRESS			0x05
+#define REQ_GET_DESCRIPTOR		0x06
+#define REQ_SET_DESCRIPTOR		0x07
+#define REQ_GET_CONFIGURATION	0x08
+#define REQ_SET_CONFIGURATION	0x09
+#define REQ_GET_INTERFACE		0x0A
+#define REQ_SET_INTERFACE		0x0B
+#define REQ_SYNCH_FRAME			0x0C
+
+/* class requests HID */
+#define HID_GET_REPORT			0x01
+#define HID_GET_IDLE			0x02
+#define HID_GET_PROTOCOL	 	0x03
+#define HID_SET_REPORT			0x09
+#define HID_SET_IDLE			0x0A
+#define HID_SET_PROTOCOL		0x0B
+
+/* feature selectors */
+#define FEA_ENDPOINT_HALT		0x00
+#define FEA_REMOTE_WAKEUP		0x01
+#define FEA_TEST_MODE			0x02
+
+/*
+	USB descriptors
+*/
+
+/** USB descriptor header */
+typedef struct {
+	unsigned char	bLength;			/**< descriptor length */
+	unsigned char	bDescriptorType;	/**< descriptor type */
+} TUSBDescHeader;
+
+#define DESC_DEVICE				1
+#define DESC_CONFIGURATION		2
+#define DESC_STRING				3
+#define DESC_INTERFACE			4
+#define DESC_ENDPOINT			5
+#define DESC_DEVICE_QUALIFIER	6
+#define DESC_OTHER_SPEED		7
+#define DESC_INTERFACE_POWER	8
+
+#define DESC_HID_HID			0x21
+#define DESC_HID_REPORT			0x22
+#define DESC_HID_PHYSICAL		0x23
+
+#define GET_DESC_TYPE(x)		(((x)>>8)&0xFF)
+#define GET_DESC_INDEX(x)		((x)&0xFF)
+
+#endif /* _USBSTRUCT_H_ */
+
diff --git a/gyro_board/src/usb/Makefile b/gyro_board/src/usb/Makefile
new file mode 100644
index 0000000..a87936e
--- /dev/null
+++ b/gyro_board/src/usb/Makefile
@@ -0,0 +1,63 @@
+NAME=main
+
+LDSCRIPT=lpc1758_Debug.ld
+
+CSRC=main.c
+
+GCC_PATH=/usr/local/cortex-m3/bin
+
+PORT=/dev/ttyUSB0
+
+CC=$(GCC_PATH)/arm-eabi-gcc
+LD=$(GCC_PATH)/arm-eabi-ld
+OBJCOPY=$(GCC_PATH)/arm-eabi-objcopy
+AS=$(GCC_PATH)/arm-eabi-as
+FLASHER=lpc21isp
+
+CFLAGS=-I. -I./FreeRTOS/include -I./FreeRTOS/portable/GCC/ARM_CM3/ -I./CommonDemoTasks/include -Os -mcpu=cortex-m3 -mthumb -Wl,--gc-sections -ffunction-sections -Wl,-static -Werror
+
+SPEED=38400
+OSC=12000
+
+SOURCES=main.c \
+	ParTest.c \
+	printf-stdarg.c \
+	cr_startup_lpc17.c \
+	CommonDemoTasks/flash.c \
+	FreeRTOS/portable/MemMang/heap_2.c \
+	alloc.c \
+	analog.c \
+	FreeRTOS/portable/GCC/ARM_CM3/port.c \
+	FreeRTOS/tasks.c \
+	FreeRTOS/list.c \
+	FreeRTOS/queue.c \
+	CAN.c \
+	LPCUSB/usbinit.c \
+	LPCUSB/usbcontrol.c \
+	LPCUSB/USB_SENSOR_STREAM.c \
+	LPCUSB/usbhw_lpc.c \
+	spi.c \
+	LPCUSB/usbstdreq.c
+
+all: $(NAME).hex
+
+$(NAME).elf: Makefile $(SOURCES:.c=.o) $(LDSCRIPT)
+	$(CC) $(CFLAGS) -nostartfiles -nostdlib -T $(LDSCRIPT) -o $@ -L/usr/local/cortex-m3/lib/gcc/arm-eabi/4.5.1/ $(SOURCES:.c=.o) -Wa,-Map -Wa,main.map -lgcc
+
+%.o: %.c Makefile
+	$(CC) $(CFLAGS) -nostartfiles -nostdlib -c -o $@ $< -Wall -std=gnu99
+
+run: deploy
+	$(FLASHER) -termonly $(NAME).hex $(PORT) $(SPEED) $(OSC)
+
+deploy: all $(NAME).hex
+	$(FLASHER) -hex -verify $(NAME).hex $(PORT) $(SPEED) $(OSC)
+
+cat:
+	@cd ../../bin; python serial_looper.py
+
+%.hex: %.elf Makefile
+	$(OBJCOPY) -O ihex $< $@
+
+clean:
+	rm -rf $(SOURCES:.c=.o) $(NAME).hex $(NAME).elf
diff --git a/gyro_board/src/usb/ParTest.c b/gyro_board/src/usb/ParTest.c
new file mode 100644
index 0000000..67f3a45
--- /dev/null
+++ b/gyro_board/src/usb/ParTest.c
@@ -0,0 +1,119 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    ***************************************************************************
+    *                                                                         *
+    * If you are:                                                             *
+    *                                                                         *
+    *    + New to FreeRTOS,                                                   *
+    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
+    *    + Looking for basic training,                                        *
+    *    + Wanting to improve your FreeRTOS skills and productivity           *
+    *                                                                         *
+    * then take a look at the FreeRTOS eBook                                  *
+    *                                                                         *
+    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
+    *                  http://www.FreeRTOS.org/Documentation                  *
+    *                                                                         *
+    * A pdf reference manual is also available.  Both are usually delivered   *
+    * to your inbox within 20 minutes to two hours when purchased between 8am *
+    * and 8pm GMT (although please allow up to 24 hours in case of            *
+    * exceptional circumstances).  Thank you for your support!                *
+    *                                                                         *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+    1 tab == 4 spaces!
+
+    http://www.FreeRTOS.org - Documentation, latest information, license and
+    contact details.
+
+    http://www.SafeRTOS.com - A version that is certified for use in safety
+    critical systems.
+
+    http://www.OpenRTOS.com - Commercial support, development, porting,
+    licensing and training services.
+*/
+
+/* FreeRTOS.org includes. */
+#include "FreeRTOS.h"
+
+/* Demo application includes. */
+#include "partest.h"
+
+#define LED_1 ( 1UL << 8UL )
+#define LED_2 ( 1UL << 7UL )
+#define LED_3 ( 1UL << 6UL )
+
+#define partstFIO1_BITS			( LED_2 | LED_3 | LED_1)
+#define partstNUM_LEDS			( 3 )
+
+static unsigned long ulLEDs[] = {LED_1, LED_2, LED_3};
+
+/*-----------------------------------------------------------
+ * Simple parallel port IO routines.
+ *-----------------------------------------------------------*/
+
+void vParTestInitialise(void)
+{
+        /* LEDs on port 2. */
+        GPIO2->FIODIR |= partstFIO1_BITS;
+        //GPIO0->FIODIR = LED_4;
+
+        /* Start will all LEDs off. */
+        GPIO2->FIOCLR = partstFIO1_BITS;
+        //GPIO0->FIOSET = LED_4;
+	//PINCON->PINMODE0 = (PINCON->PINMODE0 & 0xfffffff0) | 0x00000001;
+}
+/*-----------------------------------------------------------*/
+
+void vParTestSetLED(unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue)
+{
+        if (uxLED < partstNUM_LEDS) {
+                if (xValue) {
+                       	GPIO2->FIOCLR = ulLEDs[uxLED];
+                } else {
+                       	GPIO2->FIOSET = ulLEDs[uxLED];
+                }
+        }
+}
+/*-----------------------------------------------------------*/
+
+void vParTestToggleLED(unsigned portBASE_TYPE uxLED)
+{
+        if (uxLED < partstNUM_LEDS) {
+               	if (GPIO2->FIOPIN & ulLEDs[uxLED]) {
+                       	GPIO2->FIOCLR = ulLEDs[uxLED];
+               	} else {
+                       	GPIO2->FIOSET = ulLEDs[uxLED];
+               	}
+        }
+}
+/*-----------------------------------------------------------*/
+
+unsigned portBASE_TYPE uxParTextGetLED(unsigned portBASE_TYPE uxLED)
+{
+        if (uxLED < partstNUM_LEDS) {
+                return (GPIO2->FIOPIN & ulLEDs[uxLED]);
+        } else {
+                return 0;
+        }
+}
+/*-----------------------------------------------------------*/
+
diff --git a/gyro_board/src/usb/alloc.c b/gyro_board/src/usb/alloc.c
new file mode 100644
index 0000000..1684551
--- /dev/null
+++ b/gyro_board/src/usb/alloc.c
@@ -0,0 +1,62 @@
+/* 
+ * This is a glue between newlib and FreeRTOS heap2 allocator !
+ * You need to understand how heap2 works and its limitations,
+ * otherwise you will run out of memory.
+ *
+ * Michal Demin - 2010
+ *
+ * TODO: reent is there for a reason !
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* definition of block structure, copied from heap2 allocator */
+typedef struct A_BLOCK_LINK
+{
+	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<< The next free block in the list. */
+	size_t xBlockSize;						/*<< The size of the free block. */
+} xBlockLink;
+
+static const unsigned short  heapSTRUCT_SIZE	= ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) );
+
+_PTR _realloc_r(struct _reent *re, _PTR oldAddr, size_t newSize) {
+	xBlockLink *block;
+	size_t toCopy;
+	void *newAddr;
+
+	newAddr = pvPortMalloc(newSize);
+
+	if (newAddr == NULL)
+		return NULL;
+
+	/* We need the block struct pointer to get the current size */
+	block = oldAddr;
+	block -= heapSTRUCT_SIZE;
+
+	/* determine the size to be copied */
+	toCopy = (newSize<block->xBlockSize)?(newSize):(block->xBlockSize);
+
+	/* copy old block into new one */
+	memcpy((void *)newAddr, (void *)oldAddr, (size_t)toCopy);
+
+	vPortFree(oldAddr);
+	
+	return newAddr;
+}
+
+_PTR _calloc_r(struct _reent *re, size_t num, size_t size) {
+	return pvPortMalloc(num*size);
+}
+
+_PTR _malloc_r(struct _reent *re, size_t size) {
+	return pvPortMalloc(size);
+}
+
+_VOID _free_r(struct _reent *re, _PTR ptr) {
+	vPortFree(ptr);
+}
+
diff --git a/gyro_board/src/usb/analog.c b/gyro_board/src/usb/analog.c
new file mode 100644
index 0000000..9e67dd5
--- /dev/null
+++ b/gyro_board/src/usb/analog.c
@@ -0,0 +1,220 @@
+// ****************************************************************************
+// CopyLeft qwerk Robotics unINC. 2010 All Rights Reserved.
+// ****************************************************************************
+
+// ****************************************************************************
+// **************** IO Pin Setup
+// ****************************************************************************
+
+#include "FreeRTOS.h"
+
+void analog_init (void)
+{
+	// b[1:0] CAN RD1 p0.0
+	// b[3:2] CAN TD1 p0.1
+	//PINCON->PINSEL0 = 0x00000005;
+
+	// b[29:28] USB_DMIN 	p0.30
+	// b[27:26] USB_DPLUS	p0.29
+	// b[21:20] AD0.3	p0.26
+	// b[19:18] AD0.2	p0.25
+	// PINCON->PINSEL1 = 0x14140000;
+
+	// PINCON->PINSEL2 = 0x0;
+
+	// b[31:30] AD0.5	p1.31
+	// b[29:28] V_BUS	p1.30
+	// b[21:20] MCOB1	p1.26
+	// b[19:18] MCOA1	p1.25
+	// b[15:14] MCI1	p1.23
+	// b[13:12] MCOB0	p1.22
+	// b[09:08] MCI0	p1.20
+	// b[07:06] MCOA0	p1.19
+	// b[05:04] USB_UP_LED	p1.18
+	//PINCON->PINSEL3 = 0xE0145150;
+	SC->PCONP |= PCONP_PCAD;
+
+	// Enable AD0.0, AD0.1, AD0.2, AD0.3
+	PINCON->PINSEL1 &= 0xFFC03FFF;
+	PINCON->PINSEL1 |= 0x00D54000;
+	ADC->ADCR = 0x00200500;
+}
+
+// ****************************************************************************
+// **************** ADC Functions
+// ****************************************************************************
+
+
+// **************** macros
+// starts convertion [26:24] = 001
+
+// **************** functions
+int analog(int channel)
+{
+	ADC->ADCR = ((ADC->ADCR & 0xF8FFFF00) | (0x01000000 | (1 << channel)));
+
+	// Poll until it is done.
+	while(!(ADC->ADGDR & 0x80000000));
+
+	return ((ADC->ADGDR & 0x0000FFF0) >> 4);
+}
+// GPIO1 P0.4
+// GPIO2 P0.5
+// GPIO3 P0.6
+// GPIO4 P0.7
+// GPIO5 P0.8
+// GPIO6 P0.9
+// GPIO7 P2.0
+// GPIO8 P2.1
+// GPIO9 P2.2
+// GPIO10 P2.3
+// GPIO11 P2.4
+// GPIO12 P2.5
+
+// DIP0 P1.29
+// DIP1 P2.13
+// DIP2 P0.11
+// DIP3 P0.10
+#define readGPIO(gpio,chan) ((((gpio)->FIOPIN) >> (chan)) & 1)
+inline int readGPIO_inline(int major,int minor){
+	switch(major){
+		case 0:
+			return readGPIO(GPIO0,minor);
+		case 1:
+			return readGPIO(GPIO1,minor);
+		case 2:
+			return readGPIO(GPIO2,minor);
+		default:
+			return -1;
+	}
+}
+int digital(int channel)
+{
+	if(channel < 1){
+		return -1;
+	}else if(channel < 7){
+		int chan = channel + 3;
+		return readGPIO(GPIO0,chan);
+	}else if(channel < 13){
+		int chan = channel - 7;
+		return readGPIO(GPIO2,chan);
+	}
+	return -1;
+}
+int dip(int channel)
+{
+	switch(channel){
+		case 0:
+			return readGPIO(GPIO1,29);
+		case 1:
+			return readGPIO(GPIO2,13);
+		case 2:
+			return readGPIO(GPIO0,11);
+		case 3:
+			return readGPIO(GPIO0,10);
+		default:
+			return -1;
+
+	}
+}
+//ENC0A 1.20
+//ENC0B 1.23
+//ENC1A 2.11
+//ENC1B 2.12
+//ENC2A 0.21
+//ENC2B 0.22
+//ENC3A 0.19
+//ENC3B 0.20
+
+#define ENC(gpio,a,b) readGPIO(gpio,a) * 2 + readGPIO(gpio,b)
+int encoder_bits(int channel)
+{
+	switch(channel){
+		case 0:
+			return ENC(GPIO1,20,23);
+		case 1:
+			return ENC(GPIO2,11,12);
+		case 2:	
+			return ENC(GPIO0,21,22);
+		case 3:	
+			return ENC(GPIO0,19,20);
+		default:
+			return -1;
+	}
+	return -1;
+}
+
+volatile int32_t encoder1_val;
+void encoder_init(void)
+{
+// port 0
+	// Setup the encoder interface.
+	SC->PCONP |= PCONP_PCQEI;
+	PINCON->PINSEL3 = ((PINCON->PINSEL3 & 0xffff3dff) | 0x00004100);
+
+	// Reset the count and velocity
+	QEI->QEICON = 0x00000005;
+
+	QEI->QEICONF = 0x00000004;
+	// Wrap back to 0 when we wrap the int...
+	QEI->QEIMAXPOS = 0xffffffff;
+// port 1
+	NVIC_EnableIRQ(EINT1_IRQn);
+	NVIC_EnableIRQ(EINT2_IRQn);
+	//NVIC_EnableIRQ(EINT3_IRQn);
+	//PINSEL4 23/22 0 1
+	//PINSEL4 25 24 0 1
+	PINCON->PINSEL4 = (PINCON->PINSEL4 & ~(0x3 << 22)) | (0x1 << 22);
+	PINCON->PINSEL4 = (PINCON->PINSEL4 & ~(0x3 << 24)) | (0x1 << 24);
+
+	//EXTMODE 1 2 1 1 // all others off
+	SC->EXTMODE = 0x6;
+	SC->EXTINT = 0x6;
+	encoder1_val = 0;
+//ports 2 and 3
+	
+
+}
+void EINT1_IRQHandler(void){
+	//ENC1A 2.11
+	int stored_val = encoder1_val;
+	int fiopin = GPIO2->FIOPIN;
+	if(((fiopin >> 1) ^ fiopin) & 0x800){
+		stored_val ++;
+	}else{
+		stored_val --;
+	}
+	encoder1_val = stored_val;
+	SC->EXTPOLAR ^= 0x2;   
+	SC->EXTINT = 0x2;
+}
+void EINT2_IRQHandler(void){
+	//ENC1B 2.12
+	int stored_val = encoder1_val;
+	int fiopin = GPIO2->FIOPIN;
+	if(((fiopin >> 1) ^ fiopin) & 0x800){
+		stored_val --;
+	}else{
+		stored_val ++;
+	}
+	encoder1_val = stored_val;
+	SC->EXTPOLAR ^= 0x4;   
+	SC->EXTINT = 0x4;
+}
+void EINT3_IRQHandler(void){
+	
+}
+int32_t encoder_val(int chan)
+{
+	switch(chan){
+		case 0:
+			return (int32_t)QEI->QEIPOS;
+		case 1:
+			return encoder1_val;
+		case 2:
+		case 3:
+		default:
+			return -1;
+	}
+}
+
diff --git a/gyro_board/src/usb/analog.h b/gyro_board/src/usb/analog.h
new file mode 100644
index 0000000..e9704f6
--- /dev/null
+++ b/gyro_board/src/usb/analog.h
@@ -0,0 +1,11 @@
+#ifndef __ANALOG_H__
+#define __ANALOG_H__
+
+void analog_init (void);
+int analog(int chan);
+int digital(int chan);
+int encoder_bits(int chan);
+void encoder_init(void);
+int32_t encoder_val(int chan);
+int dip(int chan);
+#endif // __ANALOG_H__
diff --git a/gyro_board/src/usb/core_cm3.h b/gyro_board/src/usb/core_cm3.h
new file mode 100644
index 0000000..a6e8707
--- /dev/null
+++ b/gyro_board/src/usb/core_cm3.h
@@ -0,0 +1,1376 @@
+/******************************************************************************
+ * @file:    core_cm3.h
+ * @purpose: CMSIS Cortex-M3 Core Peripheral Access Layer Header File
+ * @version: V1.20
+ * @date:    22. May 2009
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2009 ARM Limited. All rights reserved.
+ *
+ * ARM Limited (ARM) is supplying this software for use with Cortex-Mx
+ * processor based microcontrollers.  This file can be freely distributed
+ * within development tools that are supporting such ARM based processors.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ *
+ ******************************************************************************/
+
+#ifndef __CM3_CORE_H__
+#define __CM3_CORE_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define __CM3_CMSIS_VERSION_MAIN  (0x01)                                                       /*!< [31:16] CMSIS HAL main version */
+#define __CM3_CMSIS_VERSION_SUB   (0x20)                                                       /*!< [15:0]  CMSIS HAL sub version  */
+#define __CM3_CMSIS_VERSION       ((__CM3_CMSIS_VERSION_MAIN << 16) | __CM3_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number       */
+
+#define __CORTEX_M                (0x03)                                                       /*!< Cortex core                    */
+
+        /**
+         *  Lint configuration \n
+         *  ----------------------- \n
+         *
+         *  The following Lint messages will be suppressed and not shown: \n
+         *  \n
+         *    --- Error 10: --- \n
+         *    register uint32_t __regBasePri         __asm("basepri"); \n
+         *    Error 10: Expecting ';' \n
+         *     \n
+         *    --- Error 530: --- \n
+         *    return(__regBasePri); \n
+         *    Warning 530: Symbol '__regBasePri' (line 264) not initialized \n
+         *     \n
+         *    --- Error 550: --- \n
+         *      __regBasePri = (basePri & 0x1ff); \n
+         *    } \n
+         *    Warning 550: Symbol '__regBasePri' (line 271) not accessed \n
+         *     \n
+         *    --- Error 754: --- \n
+         *    uint32_t RESERVED0[24]; \n
+         *    Info 754: local structure member '<some, not used in the HAL>' (line 109, file ./cm3_core.h) not referenced \n
+         *     \n
+         *    --- Error 750: --- \n
+         *    #define __CM3_CORE_H__ \n
+         *    Info 750: local macro '__CM3_CORE_H__' (line 43, file./cm3_core.h) not referenced \n
+         *     \n
+         *    --- Error 528: --- \n
+         *    static __INLINE void NVIC_DisableIRQ(uint32_t IRQn) \n
+         *    Warning 528: Symbol 'NVIC_DisableIRQ(unsigned int)' (line 419, file ./cm3_core.h) not referenced \n
+         *     \n
+         *    --- Error 751: --- \n
+         *    } InterruptType_Type; \n
+         *    Info 751: local typedef 'InterruptType_Type' (line 170, file ./cm3_core.h) not referenced \n
+         * \n
+         * \n
+         *    Note:  To re-enable a Message, insert a space before 'lint' * \n
+         *
+         */
+
+        /*lint -save */
+        /*lint -e10  */
+        /*lint -e530 */
+        /*lint -e550 */
+        /*lint -e754 */
+        /*lint -e750 */
+        /*lint -e528 */
+        /*lint -e751 */
+
+
+#include <stdint.h>                           /* Include standard types */
+
+#if defined (__ICCARM__)
+#include <intrinsics.h>                     /* IAR Intrinsics   */
+#endif
+
+
+#ifndef __NVIC_PRIO_BITS
+#define __NVIC_PRIO_BITS    4               /*!< standard definition for NVIC Priority Bits */
+#endif
+
+
+
+
+        /**
+         * IO definitions
+         *
+         * define access restrictions to peripheral registers
+         */
+
+#ifdef __cplusplus
+#define     __I     volatile                  /*!< defines 'read only' permissions      */
+#else
+#define     __I     volatile const            /*!< defines 'read only' permissions      */
+#endif
+#define     __O     volatile                  /*!< defines 'write only' permissions     */
+#define     __IO    volatile                  /*!< defines 'read / write' permissions   */
+
+
+
+        /*******************************************************************************
+         *                 Register Abstraction
+         ******************************************************************************/
+
+
+        /* System Reset */
+#define NVIC_VECTRESET              0         /*!< Vector Reset Bit             */
+#define NVIC_SYSRESETREQ            2         /*!< System Reset Request         */
+#define NVIC_AIRCR_VECTKEY    (0x5FA << 16)   /*!< AIRCR Key for write access   */
+#define NVIC_AIRCR_ENDIANESS        15        /*!< Endianess                    */
+
+        /* Core Debug */
+#define CoreDebug_DEMCR_TRCENA (1 << 24)      /*!< DEMCR TRCENA enable          */
+#define ITM_TCR_ITMENA              1         /*!< ITM enable                   */
+
+
+
+
+        /* memory mapping struct for Nested Vectored Interrupt Controller (NVIC) */
+        typedef struct {
+                __IO uint32_t ISER[8];                      /*!< Interrupt Set Enable Register            */
+                uint32_t RESERVED0[24];
+                __IO uint32_t ICER[8];                      /*!< Interrupt Clear Enable Register          */
+                uint32_t RSERVED1[24];
+                __IO uint32_t ISPR[8];                      /*!< Interrupt Set Pending Register           */
+                uint32_t RESERVED2[24];
+                __IO uint32_t ICPR[8];                      /*!< Interrupt Clear Pending Register         */
+                uint32_t RESERVED3[24];
+                __IO uint32_t IABR[8];                      /*!< Interrupt Active bit Register            */
+                uint32_t RESERVED4[56];
+                __IO uint8_t  IP[240];                      /*!< Interrupt Priority Register, 8Bit wide   */
+                uint32_t RESERVED5[644];
+                __O  uint32_t STIR;                         /*!< Software Trigger Interrupt Register      */
+        }  NVIC_Type;
+
+
+        /* memory mapping struct for System Control Block */
+        typedef struct {
+                __I  uint32_t CPUID;                        /*!< CPU ID Base Register                                     */
+                __IO uint32_t ICSR;                         /*!< Interrupt Control State Register                         */
+                __IO uint32_t VTOR;                         /*!< Vector Table Offset Register                             */
+                __IO uint32_t AIRCR;                        /*!< Application Interrupt / Reset Control Register           */
+                __IO uint32_t SCR;                          /*!< System Control Register                                  */
+                __IO uint32_t CCR;                          /*!< Configuration Control Register                           */
+                __IO uint8_t  SHP[12];                      /*!< System Handlers Priority Registers (4-7, 8-11, 12-15)    */
+                __IO uint32_t SHCSR;                        /*!< System Handler Control and State Register                */
+                __IO uint32_t CFSR;                         /*!< Configurable Fault Status Register                       */
+                __IO uint32_t HFSR;                         /*!< Hard Fault Status Register                               */
+                __IO uint32_t DFSR;                         /*!< Debug Fault Status Register                              */
+                __IO uint32_t MMFAR;                        /*!< Mem Manage Address Register                              */
+                __IO uint32_t BFAR;                         /*!< Bus Fault Address Register                               */
+                __IO uint32_t AFSR;                         /*!< Auxiliary Fault Status Register                          */
+                __I  uint32_t PFR[2];                       /*!< Processor Feature Register                               */
+                __I  uint32_t DFR;                          /*!< Debug Feature Register                                   */
+                __I  uint32_t ADR;                          /*!< Auxiliary Feature Register                               */
+                __I  uint32_t MMFR[4];                      /*!< Memory Model Feature Register                            */
+                __I  uint32_t ISAR[5];                      /*!< ISA Feature Register                                     */
+        } SCB_Type;
+
+
+        /* memory mapping struct for SysTick */
+        typedef struct {
+                __IO uint32_t CTRL;                         /*!< SysTick Control and Status Register */
+                __IO uint32_t LOAD;                         /*!< SysTick Reload Value Register       */
+                __IO uint32_t VAL;                          /*!< SysTick Current Value Register      */
+                __I  uint32_t CALIB;                        /*!< SysTick Calibration Register        */
+        } SysTick_Type;
+
+
+        /* memory mapping structur for ITM */
+        typedef struct {
+                __O  union {
+                        __O  uint8_t    u8;                       /*!< ITM Stimulus Port 8-bit               */
+                        __O  uint16_t   u16;                      /*!< ITM Stimulus Port 16-bit              */
+                        __O  uint32_t   u32;                      /*!< ITM Stimulus Port 32-bit              */
+                }  PORT [32];                               /*!< ITM Stimulus Port Registers           */
+                uint32_t RESERVED0[864];
+                __IO uint32_t TER;                          /*!< ITM Trace Enable Register             */
+                uint32_t RESERVED1[15];
+                __IO uint32_t TPR;                          /*!< ITM Trace Privilege Register          */
+                uint32_t RESERVED2[15];
+                __IO uint32_t TCR;                          /*!< ITM Trace Control Register            */
+                uint32_t RESERVED3[29];
+                __IO uint32_t IWR;                          /*!< ITM Integration Write Register        */
+                __IO uint32_t IRR;                          /*!< ITM Integration Read Register         */
+                __IO uint32_t IMCR;                         /*!< ITM Integration Mode Control Register */
+                uint32_t RESERVED4[43];
+                __IO uint32_t LAR;                          /*!< ITM Lock Access Register              */
+                __IO uint32_t LSR;                          /*!< ITM Lock Status Register              */
+                uint32_t RESERVED5[6];
+                __I  uint32_t PID4;                         /*!< ITM Product ID Registers              */
+                __I  uint32_t PID5;
+                __I  uint32_t PID6;
+                __I  uint32_t PID7;
+                __I  uint32_t PID0;
+                __I  uint32_t PID1;
+                __I  uint32_t PID2;
+                __I  uint32_t PID3;
+                __I  uint32_t CID0;
+                __I  uint32_t CID1;
+                __I  uint32_t CID2;
+                __I  uint32_t CID3;
+        } ITM_Type;
+
+
+        /* memory mapped struct for Interrupt Type */
+        typedef struct {
+                uint32_t RESERVED0;
+                __I  uint32_t ICTR;                         /*!< Interrupt Control Type Register  */
+#if ((defined __CM3_REV) && (__CM3_REV >= 0x200))
+                __IO uint32_t ACTLR;                        /*!< Auxiliary Control Register       */
+#else
+                uint32_t RESERVED1;
+#endif
+        } InterruptType_Type;
+
+
+        /* Memory Protection Unit */
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1)
+        typedef struct {
+                __I  uint32_t TYPE;                         /*!< MPU Type Register                               */
+                __IO uint32_t CTRL;                         /*!< MPU Control Register                            */
+                __IO uint32_t RNR;                          /*!< MPU Region RNRber Register                      */
+                __IO uint32_t RBAR;                         /*!< MPU Region Base Address Register                */
+                __IO uint32_t RASR;                         /*!< MPU Region Attribute and Size Register          */
+                __IO uint32_t RBAR_A1;                      /*!< MPU Alias 1 Region Base Address Register        */
+                __IO uint32_t RASR_A1;                      /*!< MPU Alias 1 Region Attribute and Size Register  */
+                __IO uint32_t RBAR_A2;                      /*!< MPU Alias 2 Region Base Address Register        */
+                __IO uint32_t RASR_A2;                      /*!< MPU Alias 2 Region Attribute and Size Register  */
+                __IO uint32_t RBAR_A3;                      /*!< MPU Alias 3 Region Base Address Register        */
+                __IO uint32_t RASR_A3;                      /*!< MPU Alias 3 Region Attribute and Size Register  */
+        } MPU_Type;
+#endif
+
+
+        /* Core Debug Register */
+        typedef struct {
+                __IO uint32_t DHCSR;                        /*!< Debug Halting Control and Status Register       */
+                __O  uint32_t DCRSR;                        /*!< Debug Core Register Selector Register           */
+                __IO uint32_t DCRDR;                        /*!< Debug Core Register Data Register               */
+                __IO uint32_t DEMCR;                        /*!< Debug Exception and Monitor Control Register    */
+        } CoreDebug_Type;
+
+
+        /* Memory mapping of Cortex-M3 Hardware */
+#define SCS_BASE            (0xE000E000)                              /*!< System Control Space Base Address    */
+#define ITM_BASE            (0xE0000000)                              /*!< ITM Base Address                     */
+#define CoreDebug_BASE      (0xE000EDF0)                              /*!< Core Debug Base Address              */
+#define SysTick_BASE        (SCS_BASE +  0x0010)                      /*!< SysTick Base Address                 */
+#define NVIC_BASE           (SCS_BASE +  0x0100)                      /*!< NVIC Base Address                    */
+#define SCB_BASE            (SCS_BASE +  0x0D00)                      /*!< System Control Block Base Address    */
+
+#define InterruptType       ((InterruptType_Type *) SCS_BASE)         /*!< Interrupt Type Register              */
+#define SCB                 ((SCB_Type *)           SCB_BASE)         /*!< SCB configuration struct             */
+#define SysTick             ((SysTick_Type *)       SysTick_BASE)     /*!< SysTick configuration struct         */
+#define NVIC                ((NVIC_Type *)          NVIC_BASE)        /*!< NVIC configuration struct            */
+#define ITM                 ((ITM_Type *)           ITM_BASE)         /*!< ITM configuration struct             */
+#define CoreDebug           ((CoreDebug_Type *)     CoreDebug_BASE)   /*!< Core Debug configuration struct      */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1)
+#define MPU_BASE          (SCS_BASE +  0x0D90)                      /*!< Memory Protection Unit               */
+#define MPU               ((MPU_Type*)            MPU_BASE)         /*!< Memory Protection Unit               */
+#endif
+
+
+
+        /*******************************************************************************
+         *                Hardware Abstraction Layer
+         ******************************************************************************/
+
+
+#if defined ( __CC_ARM   )
+#define __ASM            __asm                                      /*!< asm keyword for ARM Compiler          */
+#define __INLINE         __inline                                   /*!< inline keyword for ARM Compiler       */
+
+#elif defined ( __ICCARM__ )
+#define __ASM           __asm                                       /*!< asm keyword for IAR Compiler           */
+#define __INLINE        inline                                      /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
+
+#elif defined   (  __GNUC__  )
+#define __ASM            __asm                                      /*!< asm keyword for GNU Compiler          */
+#define __INLINE         inline                                     /*!< inline keyword for GNU Compiler       */
+
+#elif defined   (  __TASKING__  )
+#define __ASM            __asm                                      /*!< asm keyword for TASKING Compiler          */
+#define __INLINE         inline                                     /*!< inline keyword for TASKING Compiler       */
+
+#endif
+
+
+        /* ###################  Compiler specific Intrinsics  ########################### */
+
+#if defined ( __CC_ARM   ) /*------------------RealView Compiler -----------------*/
+        /* ARM armcc specific functions */
+
+#define __enable_fault_irq                __enable_fiq
+#define __disable_fault_irq               __disable_fiq
+
+#define __NOP                             __nop
+#define __WFI                             __wfi
+#define __WFE                             __wfe
+#define __SEV                             __sev
+#define __ISB()                           __isb(0)
+#define __DSB()                           __dsb(0)
+#define __DMB()                           __dmb(0)
+#define __REV                             __rev
+#define __RBIT                            __rbit
+#define __LDREXB(ptr)                     ((unsigned char ) __ldrex(ptr))
+#define __LDREXH(ptr)                     ((unsigned short) __ldrex(ptr))
+#define __LDREXW(ptr)                     ((unsigned int  ) __ldrex(ptr))
+#define __STREXB(value, ptr)              __strex(value, ptr)
+#define __STREXH(value, ptr)              __strex(value, ptr)
+#define __STREXW(value, ptr)              __strex(value, ptr)
+
+
+        /* intrinsic unsigned long long __ldrexd(volatile void *ptr) */
+        /* intrinsic int __strexd(unsigned long long val, volatile void *ptr) */
+        /* intrinsic void __enable_irq();     */
+        /* intrinsic void __disable_irq();    */
+
+
+        /**
+         * @brief  Return the Process Stack Pointer
+         *
+         * @param  none
+         * @return uint32_t ProcessStackPointer
+         *
+         * Return the actual process stack pointer
+         */
+        extern uint32_t __get_PSP(void);
+
+        /**
+         * @brief  Set the Process Stack Pointer
+         *
+         * @param  uint32_t Process Stack Pointer
+         * @return none
+         *
+         * Assign the value ProcessStackPointer to the MSP
+         * (process stack pointer) Cortex processor register
+         */
+        extern void __set_PSP(uint32_t topOfProcStack);
+
+        /**
+         * @brief  Return the Main Stack Pointer
+         *
+         * @param  none
+         * @return uint32_t Main Stack Pointer
+         *
+         * Return the current value of the MSP (main stack pointer)
+         * Cortex processor register
+         */
+        extern uint32_t __get_MSP(void);
+
+        /**
+         * @brief  Set the Main Stack Pointer
+         *
+         * @param  uint32_t Main Stack Pointer
+         * @return none
+         *
+         * Assign the value mainStackPointer to the MSP
+         * (main stack pointer) Cortex processor register
+         */
+        extern void __set_MSP(uint32_t topOfMainStack);
+
+        /**
+         * @brief  Reverse byte order in unsigned short value
+         *
+         * @param  uint16_t value to reverse
+         * @return uint32_t reversed value
+         *
+         * Reverse byte order in unsigned short value
+         */
+        extern uint32_t __REV16(uint16_t value);
+
+        /*
+         * @brief  Reverse byte order in signed short value with sign extension to integer
+         *
+         * @param  int16_t value to reverse
+         * @return int32_t reversed value
+         *
+         * Reverse byte order in signed short value with sign extension to integer
+         */
+        extern int32_t __REVSH(int16_t value);
+
+
+#if (__ARMCC_VERSION < 400000)
+
+        /**
+         * @brief  Remove the exclusive lock created by ldrex
+         *
+         * @param  none
+         * @return none
+         *
+         * Removes the exclusive lock which is created by ldrex.
+         */
+        extern void __CLREX(void);
+
+        /**
+         * @brief  Return the Base Priority value
+         *
+         * @param  none
+         * @return uint32_t BasePriority
+         *
+         * Return the content of the base priority register
+         */
+        extern uint32_t __get_BASEPRI(void);
+
+        /**
+         * @brief  Set the Base Priority value
+         *
+         * @param  uint32_t BasePriority
+         * @return none
+         *
+         * Set the base priority register
+         */
+        extern void __set_BASEPRI(uint32_t basePri);
+
+        /**
+         * @brief  Return the Priority Mask value
+         *
+         * @param  none
+         * @return uint32_t PriMask
+         *
+         * Return the state of the priority mask bit from the priority mask
+         * register
+         */
+        extern uint32_t __get_PRIMASK(void);
+
+        /**
+         * @brief  Set the Priority Mask value
+         *
+         * @param  uint32_t PriMask
+         * @return none
+         *
+         * Set the priority mask bit in the priority mask register
+         */
+        extern void __set_PRIMASK(uint32_t priMask);
+
+        /**
+         * @brief  Return the Fault Mask value
+         *
+         * @param  none
+         * @return uint32_t FaultMask
+         *
+         * Return the content of the fault mask register
+         */
+        extern uint32_t __get_FAULTMASK(void);
+
+        /**
+         * @brief  Set the Fault Mask value
+         *
+         * @param  uint32_t faultMask value
+         * @return none
+         *
+         * Set the fault mask register
+         */
+        extern void __set_FAULTMASK(uint32_t faultMask);
+
+        /**
+         * @brief  Return the Control Register value
+         *
+         * @param  none
+         * @return uint32_t Control value
+         *
+         * Return the content of the control register
+         */
+        extern uint32_t __get_CONTROL(void);
+
+        /**
+         * @brief  Set the Control Register value
+         *
+         * @param  uint32_t Control value
+         * @return none
+         *
+         * Set the control register
+         */
+        extern void __set_CONTROL(uint32_t control);
+
+#else  /* (__ARMCC_VERSION >= 400000)  */
+
+
+        /**
+         * @brief  Remove the exclusive lock created by ldrex
+         *
+         * @param  none
+         * @return none
+         *
+         * Removes the exclusive lock which is created by ldrex.
+         */
+#define __CLREX                           __clrex
+
+        /**
+         * @brief  Return the Base Priority value
+         *
+         * @param  none
+         * @return uint32_t BasePriority
+         *
+         * Return the content of the base priority register
+         */
+        static __INLINE uint32_t  __get_BASEPRI(void) {
+                register uint32_t __regBasePri         __ASM("basepri");
+                return(__regBasePri);
+        }
+
+        /**
+         * @brief  Set the Base Priority value
+         *
+         * @param  uint32_t BasePriority
+         * @return none
+         *
+         * Set the base priority register
+         */
+        static __INLINE void __set_BASEPRI(uint32_t basePri) {
+                register uint32_t __regBasePri         __ASM("basepri");
+                __regBasePri = (basePri & 0x1ff);
+        }
+
+        /**
+         * @brief  Return the Priority Mask value
+         *
+         * @param  none
+         * @return uint32_t PriMask
+         *
+         * Return the state of the priority mask bit from the priority mask
+         * register
+         */
+        static __INLINE uint32_t __get_PRIMASK(void) {
+                register uint32_t __regPriMask         __ASM("primask");
+                return(__regPriMask);
+        }
+
+        /**
+         * @brief  Set the Priority Mask value
+         *
+         * @param  uint32_t PriMask
+         * @return none
+         *
+         * Set the priority mask bit in the priority mask register
+         */
+        static __INLINE void __set_PRIMASK(uint32_t priMask) {
+                register uint32_t __regPriMask         __ASM("primask");
+                __regPriMask = (priMask);
+        }
+
+        /**
+         * @brief  Return the Fault Mask value
+         *
+         * @param  none
+         * @return uint32_t FaultMask
+         *
+         * Return the content of the fault mask register
+         */
+        static __INLINE uint32_t __get_FAULTMASK(void) {
+                register uint32_t __regFaultMask       __ASM("faultmask");
+                return(__regFaultMask);
+        }
+
+        /**
+         * @brief  Set the Fault Mask value
+         *
+         * @param  uint32_t faultMask value
+         * @return none
+         *
+         * Set the fault mask register
+         */
+        static __INLINE void __set_FAULTMASK(uint32_t faultMask) {
+                register uint32_t __regFaultMask       __ASM("faultmask");
+                __regFaultMask = (faultMask & 1);
+        }
+
+        /**
+         * @brief  Return the Control Register value
+         *
+         * @param  none
+         * @return uint32_t Control value
+         *
+         * Return the content of the control register
+         */
+        static __INLINE uint32_t __get_CONTROL(void) {
+                register uint32_t __regControl         __ASM("control");
+                return(__regControl);
+        }
+
+        /**
+         * @brief  Set the Control Register value
+         *
+         * @param  uint32_t Control value
+         * @return none
+         *
+         * Set the control register
+         */
+        static __INLINE void __set_CONTROL(uint32_t control) {
+                register uint32_t __regControl         __ASM("control");
+                __regControl = control;
+        }
+
+#endif /* __ARMCC_VERSION  */
+
+
+
+#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
+        /* IAR iccarm specific functions */
+
+#define __enable_irq                              __enable_interrupt        /*!< global Interrupt enable */
+#define __disable_irq                             __disable_interrupt       /*!< global Interrupt disable */
+
+        static __INLINE void __enable_fault_irq()         {
+                __ASM("cpsie f");
+        }
+        static __INLINE void __disable_fault_irq()        {
+                __ASM("cpsid f");
+        }
+
+#define __NOP                                     __no_operation()          /*!< no operation intrinsic in IAR Compiler */
+        static __INLINE  void __WFI()                     {
+                __ASM("wfi");
+        }
+        static __INLINE  void __WFE()                     {
+                __ASM("wfe");
+        }
+        static __INLINE  void __SEV()                     {
+                __ASM("sev");
+        }
+        static __INLINE  void __CLREX()                   {
+                __ASM("clrex");
+        }
+
+        /* intrinsic void __ISB(void)                                     */
+        /* intrinsic void __DSB(void)                                     */
+        /* intrinsic void __DMB(void)                                     */
+        /* intrinsic void __set_PRIMASK();                                */
+        /* intrinsic void __get_PRIMASK();                                */
+        /* intrinsic void __set_FAULTMASK();                              */
+        /* intrinsic void __get_FAULTMASK();                              */
+        /* intrinsic uint32_t __REV(uint32_t value);                      */
+        /* intrinsic uint32_t __REVSH(uint32_t value);                    */
+        /* intrinsic unsigned long __STREX(unsigned long, unsigned long); */
+        /* intrinsic unsigned long __LDREX(unsigned long *);              */
+
+
+        /**
+         * @brief  Return the Process Stack Pointer
+         *
+         * @param  none
+         * @return uint32_t ProcessStackPointer
+         *
+         * Return the actual process stack pointer
+         */
+        extern uint32_t __get_PSP(void);
+
+        /**
+         * @brief  Set the Process Stack Pointer
+         *
+         * @param  uint32_t Process Stack Pointer
+         * @return none
+         *
+         * Assign the value ProcessStackPointer to the MSP
+         * (process stack pointer) Cortex processor register
+         */
+        extern void __set_PSP(uint32_t topOfProcStack);
+
+        /**
+         * @brief  Return the Main Stack Pointer
+         *
+         * @param  none
+         * @return uint32_t Main Stack Pointer
+         *
+         * Return the current value of the MSP (main stack pointer)
+         * Cortex processor register
+         */
+        extern uint32_t __get_MSP(void);
+
+        /**
+         * @brief  Set the Main Stack Pointer
+         *
+         * @param  uint32_t Main Stack Pointer
+         * @return none
+         *
+         * Assign the value mainStackPointer to the MSP
+         * (main stack pointer) Cortex processor register
+         */
+        extern void __set_MSP(uint32_t topOfMainStack);
+
+        /**
+         * @brief  Reverse byte order in unsigned short value
+         *
+         * @param  uint16_t value to reverse
+         * @return uint32_t reversed value
+         *
+         * Reverse byte order in unsigned short value
+         */
+        extern uint32_t __REV16(uint16_t value);
+
+        /**
+         * @brief  Reverse bit order of value
+         *
+         * @param  uint32_t value to reverse
+         * @return uint32_t reversed value
+         *
+         * Reverse bit order of value
+         */
+        extern uint32_t __RBIT(uint32_t value);
+
+        /**
+         * @brief  LDR Exclusive
+         *
+         * @param  uint8_t* address
+         * @return uint8_t value of (*address)
+         *
+         * Exclusive LDR command
+         */
+        extern uint8_t __LDREXB(uint8_t *addr);
+
+        /**
+         * @brief  LDR Exclusive
+         *
+         * @param  uint16_t* address
+         * @return uint16_t value of (*address)
+         *
+         * Exclusive LDR command
+         */
+        extern uint16_t __LDREXH(uint16_t *addr);
+
+        /**
+         * @brief  LDR Exclusive
+         *
+         * @param  uint32_t* address
+         * @return uint32_t value of (*address)
+         *
+         * Exclusive LDR command
+         */
+        extern uint32_t __LDREXW(uint32_t *addr);
+
+        /**
+         * @brief  STR Exclusive
+         *
+         * @param  uint8_t *address
+         * @param  uint8_t value to store
+         * @return uint32_t successful / failed
+         *
+         * Exclusive STR command
+         */
+        extern uint32_t __STREXB(uint8_t value, uint8_t *addr);
+
+        /**
+         * @brief  STR Exclusive
+         *
+         * @param  uint16_t *address
+         * @param  uint16_t value to store
+         * @return uint32_t successful / failed
+         *
+         * Exclusive STR command
+         */
+        extern uint32_t __STREXH(uint16_t value, uint16_t *addr);
+
+        /**
+         * @brief  STR Exclusive
+         *
+         * @param  uint32_t *address
+         * @param  uint32_t value to store
+         * @return uint32_t successful / failed
+         *
+         * Exclusive STR command
+         */
+        extern uint32_t __STREXW(uint32_t value, uint32_t *addr);
+
+
+
+#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
+        /* GNU gcc specific functions */
+
+        static __INLINE void __enable_irq()               {
+                __ASM volatile("cpsie i");
+        }
+        static __INLINE void __disable_irq()              {
+                __ASM volatile("cpsid i");
+        }
+
+        static __INLINE void __enable_fault_irq()         {
+                __ASM volatile("cpsie f");
+        }
+        static __INLINE void __disable_fault_irq()        {
+                __ASM volatile("cpsid f");
+        }
+
+        static __INLINE void __NOP()                      {
+                __ASM volatile("nop");
+        }
+        static __INLINE void __WFI()                      {
+                __ASM volatile("wfi");
+        }
+        static __INLINE void __WFE()                      {
+                __ASM volatile("wfe");
+        }
+        static __INLINE void __SEV()                      {
+                __ASM volatile("sev");
+        }
+        static __INLINE void __ISB()                      {
+                __ASM volatile("isb");
+        }
+        static __INLINE void __DSB()                      {
+                __ASM volatile("dsb");
+        }
+        static __INLINE void __DMB()                      {
+                __ASM volatile("dmb");
+        }
+        static __INLINE void __CLREX()                    {
+                __ASM volatile("clrex");
+        }
+
+
+        /**
+         * @brief  Return the Process Stack Pointer
+         *
+         * @param  none
+         * @return uint32_t ProcessStackPointer
+         *
+         * Return the actual process stack pointer
+         */
+        extern uint32_t __get_PSP(void);
+
+        /**
+         * @brief  Set the Process Stack Pointer
+         *
+         * @param  uint32_t Process Stack Pointer
+         * @return none
+         *
+         * Assign the value ProcessStackPointer to the MSP
+         * (process stack pointer) Cortex processor register
+         */
+        extern void __set_PSP(uint32_t topOfProcStack);
+
+        /**
+         * @brief  Return the Main Stack Pointer
+         *
+         * @param  none
+         * @return uint32_t Main Stack Pointer
+         *
+         * Return the current value of the MSP (main stack pointer)
+         * Cortex processor register
+         */
+        extern uint32_t __get_MSP(void);
+
+        /**
+         * @brief  Set the Main Stack Pointer
+         *
+         * @param  uint32_t Main Stack Pointer
+         * @return none
+         *
+         * Assign the value mainStackPointer to the MSP
+         * (main stack pointer) Cortex processor register
+         */
+        extern void __set_MSP(uint32_t topOfMainStack);
+
+        /**
+         * @brief  Return the Base Priority value
+         *
+         * @param  none
+         * @return uint32_t BasePriority
+         *
+         * Return the content of the base priority register
+         */
+        extern uint32_t __get_BASEPRI(void);
+
+        /**
+         * @brief  Set the Base Priority value
+         *
+         * @param  uint32_t BasePriority
+         * @return none
+         *
+         * Set the base priority register
+         */
+        extern void __set_BASEPRI(uint32_t basePri);
+
+        /**
+         * @brief  Return the Priority Mask value
+         *
+         * @param  none
+         * @return uint32_t PriMask
+         *
+         * Return the state of the priority mask bit from the priority mask
+         * register
+         */
+        extern uint32_t  __get_PRIMASK(void);
+
+        /**
+         * @brief  Set the Priority Mask value
+         *
+         * @param  uint32_t PriMask
+         * @return none
+         *
+         * Set the priority mask bit in the priority mask register
+         */
+        extern void __set_PRIMASK(uint32_t priMask);
+
+        /**
+         * @brief  Return the Fault Mask value
+         *
+         * @param  none
+         * @return uint32_t FaultMask
+         *
+         * Return the content of the fault mask register
+         */
+        extern uint32_t __get_FAULTMASK(void);
+
+        /**
+         * @brief  Set the Fault Mask value
+         *
+         * @param  uint32_t faultMask value
+         * @return none
+         *
+         * Set the fault mask register
+         */
+        extern void __set_FAULTMASK(uint32_t faultMask);
+
+        /**
+         * @brief  Return the Control Register value
+        *
+        *  @param  none
+        *  @return uint32_t Control value
+         *
+         * Return the content of the control register
+         */
+        extern uint32_t __get_CONTROL(void);
+
+        /**
+         * @brief  Set the Control Register value
+         *
+         * @param  uint32_t Control value
+         * @return none
+         *
+         * Set the control register
+         */
+        extern void __set_CONTROL(uint32_t control);
+
+        /**
+         * @brief  Reverse byte order in integer value
+         *
+         * @param  uint32_t value to reverse
+         * @return uint32_t reversed value
+         *
+         * Reverse byte order in integer value
+         */
+        extern uint32_t __REV(uint32_t value);
+
+        /**
+         * @brief  Reverse byte order in unsigned short value
+         *
+         * @param  uint16_t value to reverse
+         * @return uint32_t reversed value
+         *
+         * Reverse byte order in unsigned short value
+         */
+        extern uint32_t __REV16(uint16_t value);
+
+        /*
+         * Reverse byte order in signed short value with sign extension to integer
+         *
+         * @param  int16_t value to reverse
+         * @return int32_t reversed value
+         *
+         * @brief  Reverse byte order in signed short value with sign extension to integer
+         */
+        extern int32_t __REVSH(int16_t value);
+
+        /**
+         * @brief  Reverse bit order of value
+         *
+         * @param  uint32_t value to reverse
+         * @return uint32_t reversed value
+         *
+         * Reverse bit order of value
+         */
+        extern uint32_t __RBIT(uint32_t value);
+
+        /**
+         * @brief  LDR Exclusive
+         *
+         * @param  uint8_t* address
+         * @return uint8_t value of (*address)
+         *
+         * Exclusive LDR command
+         */
+        extern uint8_t __LDREXB(uint8_t *addr);
+
+        /**
+         * @brief  LDR Exclusive
+         *
+         * @param  uint16_t* address
+         * @return uint16_t value of (*address)
+         *
+         * Exclusive LDR command
+         */
+        extern uint16_t __LDREXH(uint16_t *addr);
+
+        /**
+         * @brief  LDR Exclusive
+         *
+         * @param  uint32_t* address
+         * @return uint32_t value of (*address)
+         *
+         * Exclusive LDR command
+         */
+        extern uint32_t __LDREXW(uint32_t *addr);
+
+        /**
+         * @brief  STR Exclusive
+         *
+         * @param  uint8_t *address
+         * @param  uint8_t value to store
+         * @return uint32_t successful / failed
+         *
+         * Exclusive STR command
+         */
+        extern uint32_t __STREXB(uint8_t value, uint8_t *addr);
+
+        /**
+         * @brief  STR Exclusive
+         *
+         * @param  uint16_t *address
+         * @param  uint16_t value to store
+         * @return uint32_t successful / failed
+         *
+         * Exclusive STR command
+         */
+        extern uint32_t __STREXH(uint16_t value, uint16_t *addr);
+
+        /**
+         * @brief  STR Exclusive
+         *
+         * @param  uint32_t *address
+         * @param  uint32_t value to store
+         * @return uint32_t successful / failed
+         *
+         * Exclusive STR command
+         */
+        extern uint32_t __STREXW(uint32_t value, uint32_t *addr);
+
+
+#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/
+        /* TASKING carm specific functions */
+
+        /*
+         * The CMSIS functions have been implemented as intrinsics in the compiler.
+         * Please use "carm -?i" to get an up to date list of all instrinsics,
+         * Including the CMSIS ones.
+         */
+
+#endif
+
+
+
+        /* ##########################   NVIC functions  #################################### */
+
+
+        /**
+         * @brief  Set the Priority Grouping in NVIC Interrupt Controller
+         *
+         * @param  uint32_t priority_grouping is priority grouping field
+         * @return none
+         *
+         * Set the priority grouping field using the required unlock sequence.
+         * The parameter priority_grouping is assigned to the field
+         * SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used.
+         * In case of a conflict between priority grouping and available
+         * priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+         */
+        static __INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) {
+                uint32_t reg_value;
+                uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);                         /* only values 0..7 are used          */
+
+                reg_value  = SCB->AIRCR;                                                    /* read old register configuration    */
+                reg_value &= ~((0xFFFFU << 16) | (0x0F << 8));                              /* clear bits to change               */
+                reg_value  = ((reg_value | NVIC_AIRCR_VECTKEY | (PriorityGroupTmp << 8)));  /* Insert write key and priorty group */
+                SCB->AIRCR = reg_value;
+        }
+
+        /**
+         * @brief  Get the Priority Grouping from NVIC Interrupt Controller
+         *
+         * @param  none
+         * @return uint32_t   priority grouping field
+         *
+         * Get the priority grouping from NVIC Interrupt Controller.
+         * priority grouping is SCB->AIRCR [10:8] PRIGROUP field.
+         */
+        static __INLINE uint32_t NVIC_GetPriorityGrouping(void) {
+                return ((SCB->AIRCR >> 8) & 0x07);                                          /* read priority grouping field */
+        }
+
+        /**
+         * @brief  Enable Interrupt in NVIC Interrupt Controller
+         *
+         * @param  IRQn_Type IRQn specifies the interrupt number
+         * @return none
+         *
+         * Enable a device specific interupt in the NVIC interrupt controller.
+         * The interrupt number cannot be a negative value.
+         */
+        static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) {
+                NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */
+        }
+
+        /**
+         * @brief  Disable the interrupt line for external interrupt specified
+         *
+         * @param  IRQn_Type IRQn is the positive number of the external interrupt
+         * @return none
+         *
+         * Disable a device specific interupt in the NVIC interrupt controller.
+         * The interrupt number cannot be a negative value.
+         */
+        static __INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) {
+                NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */
+        }
+
+        /**
+         * @brief  Read the interrupt pending bit for a device specific interrupt source
+         *
+         * @param  IRQn_Type IRQn is the number of the device specifc interrupt
+         * @return uint32_t 1 if pending interrupt else 0
+         *
+         * Read the pending register in NVIC and return 1 if its status is pending,
+         * otherwise it returns 0
+         */
+        static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) {
+                return((uint32_t)((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0)); /* Return 1 if pending else 0 */
+        }
+
+        /**
+         * @brief  Set the pending bit for an external interrupt
+         *
+         * @param  IRQn_Type IRQn is the Number of the interrupt
+         * @return none
+         *
+         * Set the pending bit for the specified interrupt.
+         * The interrupt number cannot be a negative value.
+         */
+        static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) {
+                NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */
+        }
+
+        /**
+         * @brief  Clear the pending bit for an external interrupt
+         *
+         * @param  IRQn_Type IRQn is the Number of the interrupt
+         * @return none
+         *
+         * Clear the pending bit for the specified interrupt.
+         * The interrupt number cannot be a negative value.
+         */
+        static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) {
+                NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
+        }
+
+        /**
+         * @brief  Read the active bit for an external interrupt
+         *
+         * @param  IRQn_Type  IRQn is the Number of the interrupt
+         * @return uint32_t   1 if active else 0
+         *
+         * Read the active register in NVIC and returns 1 if its status is active,
+         * otherwise it returns 0.
+         */
+        static __INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) {
+                return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) ? 1 : 0)); /* Return 1 if active else 0 */
+        }
+
+        /**
+         * @brief  Set the priority for an interrupt
+         *
+         * @param  IRQn_Type IRQn is the Number of the interrupt
+         * @param  priority is the priority for the interrupt
+         * @return none
+         *
+         * Set the priority for the specified interrupt. The interrupt
+         * number can be positive to specify an external (device specific)
+         * interrupt, or negative to specify an internal (core) interrupt. \n
+         *
+         * Note: The priority cannot be set for every core interrupt.
+         */
+        static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) {
+                if (IRQn < 0) {
+                        SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);
+                } /* set Priority for Cortex-M3 System Interrupts */
+                else {
+                        NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);
+                }        /* set Priority for device specific Interrupts      */
+        }
+
+        /**
+         * @brief  Read the priority for an interrupt
+         *
+         * @param  IRQn_Type IRQn is the Number of the interrupt
+         * @return uint32_t  priority is the priority for the interrupt
+         *
+         * Read the priority for the specified interrupt. The interrupt
+         * number can be positive to specify an external (device specific)
+         * interrupt, or negative to specify an internal (core) interrupt.
+         *
+         * The returned priority value is automatically aligned to the implemented
+         * priority bits of the microcontroller.
+         *
+         * Note: The priority cannot be set for every core interrupt.
+         */
+        static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) {
+
+                if (IRQn < 0) {
+                        return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS)));
+                } /* get priority for Cortex-M3 system interrupts */
+                else {
+                        return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)]           >> (8 - __NVIC_PRIO_BITS)));
+                } /* get priority for device specific interrupts  */
+        }
+
+
+        /**
+         * @brief  Encode the priority for an interrupt
+         *
+         * @param  uint32_t PriorityGroup   is the used priority group
+         * @param  uint32_t PreemptPriority is the preemptive priority value (starting from 0)
+         * @param  uint32_t SubPriority     is the sub priority value (starting from 0)
+         * @return uint32_t                    the priority for the interrupt
+         *
+         * Encode the priority for an interrupt with the given priority group,
+         * preemptive priority value and sub priority value.
+         * In case of a conflict between priority grouping and available
+         * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set.
+         *
+         * The returned priority value can be used for NVIC_SetPriority(...) function
+         */
+        static __INLINE uint32_t NVIC_EncodePriority(uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) {
+                uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);                         /* only values 0..7 are used          */
+                uint32_t PreemptPriorityBits;
+                uint32_t SubPriorityBits;
+
+                PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
+                SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;
+
+                return (
+                               ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) |
+                               ((SubPriority     & ((1 << (SubPriorityBits)) - 1)))
+                       );
+        }
+
+
+        /**
+         * @brief  Decode the priority of an interrupt
+         *
+         * @param  uint32_t   Priority       the priority for the interrupt
+         * @param  uint32_t   PrioGroup   is the used priority group
+         * @param  uint32_t* pPreemptPrio is the preemptive priority value (starting from 0)
+         * @param  uint32_t* pSubPrio     is the sub priority value (starting from 0)
+         * @return none
+         *
+         * Decode an interrupt priority value with the given priority group to
+         * preemptive priority value and sub priority value.
+         * In case of a conflict between priority grouping and available
+         * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set.
+         *
+         * The priority value can be retrieved with NVIC_GetPriority(...) function
+         */
+        static __INLINE void NVIC_DecodePriority(uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) {
+                uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);                         /* only values 0..7 are used          */
+                uint32_t PreemptPriorityBits;
+                uint32_t SubPriorityBits;
+
+                PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
+                SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;
+
+                *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1);
+                *pSubPriority     = (Priority) & ((1 << (SubPriorityBits)) - 1);
+        }
+
+
+
+        /* ##################################    SysTick function  ############################################ */
+
+#if (!defined (__Vendor_SysTickConfig)) || (__Vendor_SysTickConfig == 0)
+
+        /* SysTick constants */
+#define SYSTICK_ENABLE              0                                          /* Config-Bit to start or stop the SysTick Timer                         */
+#define SYSTICK_TICKINT             1                                          /* Config-Bit to enable or disable the SysTick interrupt                 */
+#define SYSTICK_CLKSOURCE           2                                          /* Clocksource has the offset 2 in SysTick Control and Status Register   */
+#define SYSTICK_MAXCOUNT       ((1<<24) -1)                                    /* SysTick MaxCount                                                      */
+
+        /**
+         * @brief  Initialize and start the SysTick counter and its interrupt.
+         *
+         * @param  uint32_t ticks is the number of ticks between two interrupts
+         * @return  none
+         *
+         * Initialise the system tick timer and its interrupt and start the
+         * system tick timer / counter in free running mode to generate
+         * periodical interrupts.
+         */
+        static __INLINE uint32_t SysTick_Config(uint32_t ticks) {
+                if (ticks > SYSTICK_MAXCOUNT)  return (1);                                             /* Reload value impossible */
+
+                SysTick->LOAD  = (ticks & SYSTICK_MAXCOUNT) - 1;                                       /* set reload register */
+                NVIC_SetPriority(SysTick_IRQn, (1 << __NVIC_PRIO_BITS) - 1);                           /* set Priority for Cortex-M0 System Interrupts */
+                SysTick->VAL   = (0x00);                                                               /* Load the SysTick Counter Value */
+                SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1 << SYSTICK_ENABLE) | (1 << SYSTICK_TICKINT); /* Enable SysTick IRQ and SysTick Timer */
+                return (0);                                                                            /* Function successful */
+        }
+
+#endif
+
+
+
+
+
+        /* ##################################    Reset function  ############################################ */
+
+        /**
+         * @brief  Initiate a system reset request.
+         *
+         * @param   none
+         * @return  none
+         *
+         * Initialize a system reset request to reset the MCU
+         */
+        static __INLINE void NVIC_SystemReset(void) {
+                SCB->AIRCR  = (NVIC_AIRCR_VECTKEY | (SCB->AIRCR & (0x700)) | (1 << NVIC_SYSRESETREQ)); /* Keep priority group unchanged */
+                __DSB();                                                                             /* Ensure completion of memory access */
+                while (1);                                                                           /* wait until reset */
+        }
+
+
+        /* ##################################    Debug Output  function  ############################################ */
+
+
+        /**
+         * @brief  Outputs a character via the ITM channel 0
+         *
+         * @param   uint32_t character to output
+         * @return  uint32_t input character
+         *
+         * The function outputs a character via the ITM channel 0.
+         * The function returns when no debugger is connected that has booked the output.
+         * It is blocking when a debugger is connected, but the previous character send is not transmitted.
+         */
+        static __INLINE uint32_t ITM_SendChar(uint32_t ch) {
+                if (ch == '\n') ITM_SendChar('\r');
+
+                if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA)  &&
+                                (ITM->TCR & ITM_TCR_ITMENA)                  &&
+                                (ITM->TER & (1UL << 0))) {
+                        while (ITM->PORT[0].u32 == 0);
+                        ITM->PORT[0].u8 = (uint8_t) ch;
+                }
+                return (ch);
+        }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CM3_CORE_H__ */
+
+/*lint -restore */
diff --git a/gyro_board/src/usb/cr_startup_lpc17.c b/gyro_board/src/usb/cr_startup_lpc17.c
new file mode 100644
index 0000000..00f6187
--- /dev/null
+++ b/gyro_board/src/usb/cr_startup_lpc17.c
@@ -0,0 +1,304 @@
+//*****************************************************************************
+//   +--+
+//   | ++----+
+//   +-++    |
+//     |     |
+//   +-+--+  |
+//   | +--+--+
+//   +----+    Copyright (c) 2009 Code Red Technologies Ltd.
+//
+// Microcontroller Startup code for use with Red Suite
+//
+// Software License Agreement
+//
+// The software is owned by Code Red Technologies and/or its suppliers, and is
+// protected under applicable copyright laws.  All rights are reserved.  Any
+// use in violation of the foregoing restrictions may subject the user to criminal
+// sanctions under applicable laws, as well as to civil liability for the breach
+// of the terms and conditions of this license.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT
+// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH
+// CODE RED TECHNOLOGIES LTD.
+//
+//*****************************************************************************
+#define WEAK __attribute__ ((weak))
+#define ALIAS(f) __attribute__ ((weak, alias (#f)))
+
+//*****************************************************************************
+//
+// Forward declaration of the default handlers.
+//
+//*****************************************************************************
+void Reset_Handler(void);
+void ResetISR(void) ALIAS(Reset_Handler);
+static void NMI_Handler(void);
+static void HardFault_Handler(void);
+static void MemManage_Handler(void);
+static void BusFault_Handler(void);
+static void UsageFault_Handler(void);
+static void DebugMon_Handler(void);
+
+//*****************************************************************************
+//
+// Forward declaration of the specific IRQ handlers. These are aliased
+// to the IntDefaultHandler, which is a 'forever' loop. When the application
+// defines a handler (with the same name), this will automatically take
+// precedence over these weak definitions
+//
+//*****************************************************************************
+void WDT_IRQHandler(void) ALIAS(IntDefaultHandler);
+void TIMER0_IRQHandler(void) ALIAS(IntDefaultHandler);
+void TIMER1_IRQHandler(void) ALIAS(IntDefaultHandler);
+void TIMER2_IRQHandler(void) ALIAS(IntDefaultHandler);
+void TIMER3_IRQHandler(void) ALIAS(IntDefaultHandler);
+void UART0_IRQHandler(void) ALIAS(IntDefaultHandler);
+void UART1_IRQHandler(void) ALIAS(IntDefaultHandler);
+void UART2_IRQHandler(void) ALIAS(IntDefaultHandler);
+void UART3_IRQHandler(void) ALIAS(IntDefaultHandler);
+void PWM1_IRQHandler(void) ALIAS(IntDefaultHandler);
+void I2C0_IRQHandler(void) ALIAS(IntDefaultHandler);
+void I2C1_IRQHandler(void) ALIAS(IntDefaultHandler);
+void I2C2_IRQHandler(void) ALIAS(IntDefaultHandler);
+void SPI_IRQHandler(void) ALIAS(IntDefaultHandler);
+void SSP0_IRQHandler(void) ALIAS(IntDefaultHandler);
+void SSP1_IRQHandler(void) ALIAS(IntDefaultHandler);
+void PLL0_IRQHandler(void) ALIAS(IntDefaultHandler);
+void RTC_IRQHandler(void) ALIAS(IntDefaultHandler);
+void EINT0_IRQHandler(void) ALIAS(IntDefaultHandler);
+void EINT1_IRQHandler(void) ALIAS(IntDefaultHandler);
+void EINT2_IRQHandler(void) ALIAS(IntDefaultHandler);
+void EINT3_IRQHandler(void) ALIAS(IntDefaultHandler);
+void ADC_IRQHandler(void) ALIAS(IntDefaultHandler);
+void BOD_IRQHandler(void) ALIAS(IntDefaultHandler);
+void USB_IRQHandler(void) ALIAS(IntDefaultHandler);
+void CAN_IRQHandler(void) ALIAS(IntDefaultHandler);
+void DMA_IRQHandler(void) ALIAS(IntDefaultHandler);
+void I2S_IRQHandler(void) ALIAS(IntDefaultHandler);
+void EMAC_IRQHandler(void) ALIAS(IntDefaultHandler);
+void ENET_IRQHandler(void) ALIAS(IntDefaultHandler);
+void RIT_IRQHandler(void) ALIAS(IntDefaultHandler);
+void MCPWM_IRQHandler(void) ALIAS(IntDefaultHandler);
+void QEI_IRQHandler(void) ALIAS(IntDefaultHandler);
+void PLL1_IRQHandler(void) ALIAS(IntDefaultHandler);
+
+extern void xPortSysTickHandler(void);
+extern void xPortPendSVHandler(void);
+extern void vPortSVCHandler(void);
+
+
+//*****************************************************************************
+//
+// The entry point for the C++ library startup
+//
+//*****************************************************************************
+extern WEAK void __libc_init_array(void);
+
+//*****************************************************************************
+//
+// The entry point for the application.
+// __main() is the entry point for redlib based applications
+// main() is the entry point for newlib based applications
+//
+//*****************************************************************************
+extern WEAK void __main(void);
+extern WEAK void main(void);
+//*****************************************************************************
+//
+// External declaration for the pointer to the stack top from the Linker Script
+//
+//*****************************************************************************
+extern int _vStackTop;
+
+//*****************************************************************************
+//
+// The vector table.
+// This relies on the linker script to place at correct location in memory.
+//
+//*****************************************************************************
+typedef void (* const isr_handlers_t)(void);
+__attribute__((section(".isr_vector")))
+isr_handlers_t g_pfnVectors[] = {
+        // Core Level - CM3
+        (isr_handlers_t)&_vStackTop,					// The initial stack pointer
+        Reset_Handler,							// The reset handler
+        NMI_Handler,							// The NMI handler
+        HardFault_Handler,						// The hard fault handler
+        MemManage_Handler,						// The MPU fault handler
+        BusFault_Handler,						// The bus fault handler
+        UsageFault_Handler,						// The usage fault handler
+        0,										// Reserved
+        0,										// Reserved
+        0,										// Reserved
+        0,										// Reserved
+        vPortSVCHandler,                        // SVCall handler
+        DebugMon_Handler,						// Debug monitor handler
+        0,										// Reserved
+        xPortPendSVHandler,                     // The PendSV handler
+        xPortSysTickHandler,                    // The SysTick handler
+
+        // Chip Level - LPC17
+        WDT_IRQHandler,							// 16, 0x40 - WDT
+        TIMER0_IRQHandler,						// 17, 0x44 - TIMER0
+        TIMER1_IRQHandler,						// 18, 0x48 - TIMER1
+        TIMER2_IRQHandler,						// 19, 0x4c - TIMER2
+        TIMER3_IRQHandler,						// 20, 0x50 - TIMER3
+        UART0_IRQHandler,						// 21, 0x54 - UART0
+        UART1_IRQHandler,						// 22, 0x58 - UART1
+        UART2_IRQHandler,						// 23, 0x5c - UART2
+        UART3_IRQHandler,						// 24, 0x60 - UART3
+        PWM1_IRQHandler,						// 25, 0x64 - PWM1
+        I2C0_IRQHandler,						// 26, 0x68 - I2C0
+        I2C1_IRQHandler,						// 27, 0x6c - I2C1
+        I2C2_IRQHandler,						// 28, 0x70 - I2C2
+        SPI_IRQHandler,							// 29, 0x74 - SPI
+        SSP0_IRQHandler,						// 30, 0x78 - SSP0
+        SSP1_IRQHandler,						// 31, 0x7c - SSP1
+        PLL0_IRQHandler,						// 32, 0x80 - PLL0 (Main PLL)
+        RTC_IRQHandler,							// 33, 0x84 - RTC
+        EINT0_IRQHandler,						// 34, 0x88 - EINT0
+        EINT1_IRQHandler,						// 35, 0x8c - EINT1
+        EINT2_IRQHandler,						// 36, 0x90 - EINT2
+        EINT3_IRQHandler,						// 37, 0x94 - EINT3
+        ADC_IRQHandler,							// 38, 0x98 - ADC
+        BOD_IRQHandler,							// 39, 0x9c - BOD
+        USB_IRQHandler,							// 40, 0xA0 - USB
+        CAN_IRQHandler,							// 41, 0xa4 - CAN
+        DMA_IRQHandler,							// 42, 0xa8 - GP DMA
+        I2S_IRQHandler,							// 43, 0xac - I2S
+        EMAC_IRQHandler,						// 44, 0xb0 - Ethernet
+        RIT_IRQHandler,							// 45, 0xb4 - RITINT
+        MCPWM_IRQHandler,						// 46, 0xb8 - Motor Control PWM
+        QEI_IRQHandler,							// 47, 0xbc - Quadrature Encoder
+        PLL1_IRQHandler,						// 48, 0xc0 - PLL1 (USB PLL)
+};
+
+//*****************************************************************************
+//
+// The following are constructs created by the linker, indicating where the
+// the "data" and "bss" segments reside in memory.  The initializers for the
+// for the "data" segment resides immediately following the "text" segment.
+//
+//*****************************************************************************
+extern unsigned long _etext;
+extern unsigned long _data;
+extern unsigned long _edata;
+extern unsigned long _bss;
+extern unsigned long _ebss;
+
+//*****************************************************************************
+// Reset entry point for your code.
+// Sets up a simple runtime environment and initializes the C/C++
+// library.
+//
+//*****************************************************************************
+void Reset_Handler(void)
+{
+        unsigned long *pulSrc, *pulDest;
+
+        //
+        // Copy the data segment initializers from flash to SRAM.
+        //
+        pulSrc = &_etext;
+        for (pulDest = &_data; pulDest < &_edata;) {
+                *pulDest++ = *pulSrc++;
+        }
+
+        //
+        // Zero fill the bss segment.  This is done with inline assembly since this
+        // will clear the value of pulDest if it is not kept in a register.
+        //
+        __asm("    ldr     r0, =_bss\n"
+              "    ldr     r1, =_ebss\n"
+              "    mov     r2, #0\n"
+              "    .thumb_func\n"
+              "zero_loop:\n"
+              "        cmp     r0, r1\n"
+              "        it      lt\n"
+              "        strlt   r2, [r0], #4\n"
+              "        blt     zero_loop");
+
+        //
+        // Call C++ library initilisation, if present
+        //
+        //if (__libc_init_array)
+                //__libc_init_array() ;
+
+        //
+        // Call the application's entry point.
+        // __main() is the entry point for redlib based applications (which calls main())
+        // main() is the entry point for newlib based applications
+        //
+        //if (__main)
+                //__main() ;
+        //else
+                main() ;
+
+        //
+        // main() shouldn't return, but if it does, we'll just enter an infinite loop
+        //
+        while (1) {
+                ;
+        }
+}
+
+//*****************************************************************************
+//
+// This is the code that gets called when the processor receives a NMI.  This
+// simply enters an infinite loop, preserving the system state for examination
+// by a debugger.
+//
+//*****************************************************************************
+static void NMI_Handler(void)
+{
+        while (1) {
+        }
+}
+
+static void HardFault_Handler(void)
+{
+        while (1) {
+        }
+}
+
+static void MemManage_Handler(void)
+{
+        while (1) {
+        }
+}
+
+static void BusFault_Handler(void)
+{
+        while (1) {
+        }
+}
+
+static void UsageFault_Handler(void)
+{
+        while (1) {
+        }
+}
+
+static void DebugMon_Handler(void)
+{
+        while (1) {
+        }
+}
+
+//*****************************************************************************
+//
+// Processor ends up here if an unexpected interrupt occurs or a handler
+// is not present in the application code.
+//
+//*****************************************************************************
+static void IntDefaultHandler(void)
+{
+        //
+        // Go into an infinite loop.
+        //
+        while (1) {
+        }
+}
diff --git a/gyro_board/src/usb/lpc1758_Debug.ld b/gyro_board/src/usb/lpc1758_Debug.ld
new file mode 100644
index 0000000..ce6d093
--- /dev/null
+++ b/gyro_board/src/usb/lpc1758_Debug.ld
@@ -0,0 +1,79 @@
+/*
+ * GENERATED FILE - DO NOT EDIT
+ * (C) Code Red Technologies Ltd, 2008-9
+ * Generated C linker script file for LPC1768
+ * (created from nxp_lpc13_c.ld (v2.0.11 (200907061347)) on Thu Jul 09 12:44:31 BST 2009)
+*/
+
+GROUP(libgcc.a libc.a)
+
+MEMORY
+{
+	FLASH(rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+	SRAM(rwx) : ORIGIN = 0x10000000, LENGTH = 0x8000
+	AHBRAM0   : ORIGIN = 0x2007c000, LENGTH = 0x4000
+	AHBRAM1   : ORIGIN = 0x20080000, LENGTH = 0x4000
+}
+
+_vRamTop = 0x10000000 + 0x8000;
+
+ENTRY(ResetISR)
+
+SECTIONS {
+	.text : {
+		KEEP(*(.isr_vector))
+		*(.text*)
+		*(.rodata*)
+
+	} > FLASH
+
+
+	/* for exception handling/unwind - some Newlib functions (in common with C++ and STDC++) use this. */
+
+	.ARM.extab : {
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx : {
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	_etext = .;
+
+	.data :
+		AT(__exidx_end) {
+			_data = .;
+			*(vtable)
+			*(.data*)
+			_edata = .;
+	} > SRAM
+
+	/* zero initialized data */
+	.bss : {
+		_bss = .;
+		*(.bss*)
+		*(COMMON)
+		_ebss = .;
+	} > SRAM
+
+	/* Where we put the heap with cr_clib */
+	.cr_heap : {
+		end = .;
+		_pvHeapStart = .;
+	} > SRAM
+
+	/*
+		Note: (ref: M0000066)
+		Moving the stack down by 16 is to work around a GDB bug.
+		This space can be reclaimed for Production Builds.
+	*/
+	_vStackTop = _vRamTop - 16;
+
+	.ETHRAM : {
+	} > AHBRAM0
+
+	.USBRAM : {
+	} > AHBRAM1
+}
diff --git a/gyro_board/src/usb/main.c b/gyro_board/src/usb/main.c
new file mode 100644
index 0000000..11191a4
--- /dev/null
+++ b/gyro_board/src/usb/main.c
@@ -0,0 +1,398 @@
+/*
+    FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
+    ***NOTE*** The exception to the GPL is included to allow you to distribute
+    a combined work that includes FreeRTOS without being obliged to provide the
+    source code for proprietary components outside of the FreeRTOS kernel.
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+    more details. You should have received a copy of the GNU General Public
+    License and the FreeRTOS license exception along with FreeRTOS; if not it
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained
+    by writing to Richard Barry, contact details for whom are available on the
+    FreeRTOS WEB site.
+
+*/
+
+/* Standard includes. */
+#include "stdio.h"
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "task.h"
+
+/* Demo app includes. */
+#include "flash.h"
+#include "partest.h"
+#include "analog.h"
+#include "spi.h"
+#include "LPCUSB/usbapi.h"
+
+/*-----------------------------------------------------------*/
+
+/* The time between cycles of the 'check' functionality (defined within the
+tick hook. */
+#define mainCHECK_DELAY			((portTickType) 5000 / portTICK_RATE_MS)
+
+/* Task priorities. */
+#define mainQUEUE_POLL_PRIORITY		(tskIDLE_PRIORITY + 2)
+#define mainSEM_TEST_PRIORITY		(tskIDLE_PRIORITY + 1)
+#define mainBLOCK_Q_PRIORITY		(tskIDLE_PRIORITY + 2)
+#define mainUIP_TASK_PRIORITY		(tskIDLE_PRIORITY + 3)
+#define mainINTEGER_TASK_PRIORITY	(tskIDLE_PRIORITY)
+#define mainGEN_QUEUE_TASK_PRIORITY	(tskIDLE_PRIORITY)
+#define mainFLASH_TASK_PRIORITY		(tskIDLE_PRIORITY + 2)
+
+/* The WEB server has a larger stack as it utilises stack hungry string
+handling library calls. */
+#define mainBASIC_WEB_STACK_SIZE	(configMINIMAL_STACK_SIZE * 4)
+
+int32_t goal = 0;
+int64_t gyro_angle = 0;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Configure the hardware for the demo.
+ */
+static void prvSetupHardware(void);
+
+/*
+ * The task that handles the USB stack.
+ */
+extern void vUSBTask(void *pvParameters);
+
+extern int VCOM_getchar(void);
+
+int VCOM_putchar(int c);
+
+inline int32_t encoder()
+{
+	return (int32_t)QEI->QEIPOS;
+}
+
+static portTASK_FUNCTION(vPrintPeriodic, pvParameters)
+{
+	portTickType xLastFlashTime;
+
+	/* We need to initialise xLastFlashTime prior to the first call to
+	vTaskDelayUntil(). */
+	xLastFlashTime = xTaskGetTickCount();
+
+	analog_init();
+
+	encoder_init();
+
+	// Wait 100 ms for it to boot.
+	vTaskDelayUntil(&xLastFlashTime, 100 / portTICK_RATE_MS);
+	spi_init();
+
+	// Enable USB.  The PC has probably disconnected it now.
+	USBHwAllowConnect();
+
+	// TODO(aschuh): Write this into a gyro calibration function, and check all the outputs.
+	vTaskDelayUntil(&xLastFlashTime, 50 / portTICK_RATE_MS);
+	enable_gyro_csel();
+	printf("SPI Gyro Second Response 0x%x %x\n", transfer_spi_bytes(0x2000), transfer_spi_bytes(0x0000));
+	disable_gyro_csel();
+
+	vTaskDelayUntil(&xLastFlashTime, 50 / portTICK_RATE_MS);
+	enable_gyro_csel();
+	printf("SPI Gyro Third Response 0x%x %x\n", transfer_spi_bytes(0x2000), transfer_spi_bytes(0x0000));
+	disable_gyro_csel();
+
+	vTaskDelayUntil(&xLastFlashTime, 10 / portTICK_RATE_MS);
+	enable_gyro_csel();
+	printf("SPI Gyro Fourth Response 0x%x %x\n", transfer_spi_bytes(0x2000), transfer_spi_bytes(0x0000));
+	disable_gyro_csel();
+	const int hz = 200;
+	const int flash_hz = 10;
+	const int startup_cycles = hz * 2;
+	const int zeroing_cycles = hz * 6;
+	int32_t zero_bias = 0;
+	int32_t startup_cycles_left = startup_cycles;
+	int32_t zeroing_cycles_left = zeroing_cycles;
+	int32_t full_units_offset = 0;
+	int32_t remainder_offset = 0;
+	int32_t remainder_sum = 0;
+	int32_t led_flash = 0;
+	vParTestSetLED(0, 0);
+
+	for (;;) {
+		led_flash ++;
+		if (led_flash < hz / flash_hz / 2) {
+			vParTestSetLED(1, 0);
+		} else {
+			vParTestSetLED(1, 1);
+		}
+		if (led_flash >= hz / flash_hz) {
+			led_flash = 0;
+		}
+		/* Delay for half the flash period then turn the LED on. */
+		vTaskDelayUntil(&xLastFlashTime, 1000 / hz / portTICK_RATE_MS);
+		enable_gyro_csel();
+		uint16_t high_value = transfer_spi_bytes(0x2000);
+		uint16_t low_value = transfer_spi_bytes(0x0000);
+		disable_gyro_csel();
+		int16_t gyro_value = -((int16_t)((((uint32_t)high_value << 16) | (uint32_t)low_value) >> 10));
+
+		if (startup_cycles_left) {
+			vParTestSetLED(2, 0);
+			--startup_cycles_left;
+		} else if (zeroing_cycles_left) {
+			vParTestSetLED(2, 1);
+			//printf("Zeroing ");
+			--zeroing_cycles_left;
+			zero_bias -= gyro_value;
+			if (zeroing_cycles_left == 0) {
+				// Do all the nice math
+				full_units_offset = zero_bias / zeroing_cycles;
+				remainder_offset = zero_bias % zeroing_cycles;
+				if (remainder_offset < 0) {
+					remainder_offset += zeroing_cycles;
+					--full_units_offset;
+				}
+			}
+		} else {
+			vParTestSetLED(2, 0);
+			int64_t new_angle = gyro_angle + gyro_value + full_units_offset;
+			if (remainder_sum >= zeroing_cycles) {
+				remainder_sum -= zeroing_cycles;
+				new_angle += 1;
+			}
+			NVIC_DisableIRQ(USB_IRQn);
+			gyro_angle = new_angle;
+			NVIC_EnableIRQ(USB_IRQn);
+			remainder_sum += remainder_offset;
+		}
+		//printf("Angle %d Rate %d\n", (int)(gyro_angle / 16), (int)(gyro_value + full_units_offset));
+
+		//printf("time: %d analog %d encoder %d goal %d\n", (int)i, (int)analog(5), (int)encoder(), (int)goal);
+
+		//printf("time: %d encoder %d goal %d\n", (int)i, (int)encoder(), (int)goal);
+		/*
+		for(i = 0; i < 4; i++){
+			printf("analog(%d) => %d\n",i,analog(i));
+		}
+		for(i = 1; i < 13; i++){
+			printf("digital(%d) => %d\n",i,digital(i));
+		}
+		for(i = 0; i < 4; i++){
+			printf("dip(%d) => %d\n",i,dip(i));
+		}
+		for(i = 0; i < 4; i++){
+			printf("encoder(%d) => %d\n",i,encoder_bits(i));
+		}
+		for(i = 0; i < 4; i++){
+			printf("encoder_val(%d) => %d\n",i,(int)encoder_val(i));
+		}*/
+	}
+}
+
+#include "CAN.h"
+
+
+
+void motor(int32_t speed)
+{
+	if (speed > 2047) speed = 2047;
+	if (speed < -2047) speed = -2047;
+	return;
+	if (speed > 0) {
+		MCPWM->MCMAT1 = 2047 - speed;
+		MCPWM->MCMAT0 = 2048;
+	} else {
+		MCPWM->MCMAT1 = 2048;
+		MCPWM->MCMAT0 = speed + 2047;
+	}
+}
+
+
+
+/*-----------------------------------------------------------*/
+
+int main(void)
+{
+        // Configure the hardware
+        prvSetupHardware();
+
+        /* Start the standard demo tasks.  These are just here to exercise the
+        kernel port and provide examples of how the FreeRTOS API can be used. */
+        //vStartLEDFlashTasks(mainFLASH_TASK_PRIORITY);
+
+        /* Create the USB task. */
+        xTaskCreate(vUSBTask, (signed char *) "USB", configMINIMAL_STACK_SIZE + 1020, (void *) NULL, tskIDLE_PRIORITY + 3, NULL);
+
+	xTaskCreate(vPrintPeriodic, (signed char *) "PRINTx", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 2, NULL);
+
+	initCAN();
+
+        // Start the scheduler.
+        vTaskStartScheduler();
+
+        /* Will only get here if there was insufficient memory to create the idle
+           task.  The idle task is created within vTaskStartScheduler(). */
+        for (;;);
+}
+/*-----------------------------------------------------------*/
+
+
+void vApplicationTickHook(void)
+{
+        static unsigned long ulTicksSinceLastDisplay = 0;
+
+        /* Called from every tick interrupt as described in the comments at the top
+        of this file.
+
+        Have enough ticks passed to make it	time to perform our health status
+        check again? */
+
+        ulTicksSinceLastDisplay++;
+
+        if (ulTicksSinceLastDisplay >= mainCHECK_DELAY) {
+                /* Reset the counter so these checks run again in mainCHECK_DELAY
+                ticks time. */
+                ulTicksSinceLastDisplay = 0;
+        }
+}
+/*-----------------------------------------------------------*/
+
+void prvSetupHardware(void)
+{
+	// Setup the peripherals.
+	// The CPU will be running at 100 MHz with a 12 MHz clock input.
+
+        // Setup GPIO power.
+        SC->PCONP = PCONP_PCGPIO;
+        // Disable TPIU.
+        PINCON->PINSEL10 = 0;
+
+	// Setup PLL0 so that the CPU runs at 100 MHz.
+        if (SC->PLL0STAT & (1 << 25)) {
+                /* Enable PLL, disconnected. */
+                SC->PLL0CON = 1;
+                SC->PLL0FEED = PLLFEED_FEED1;
+                SC->PLL0FEED = PLLFEED_FEED2;
+        }
+
+        // Disable PLL, disconnected.
+        SC->PLL0CON = 0;
+        SC->PLL0FEED = PLLFEED_FEED1;
+        SC->PLL0FEED = PLLFEED_FEED2;
+
+        // Enable main OSC and wait until it's ready.
+        SC->SCS |= 0x20;
+        while (!(SC->SCS & 0x40));
+
+        // select main OSC, 12MHz, as the PLL clock source.
+        SC->CLKSRCSEL = 0x1;
+
+        SC->PLL0CFG = 0x20031;
+        SC->PLL0FEED = PLLFEED_FEED1;
+        SC->PLL0FEED = PLLFEED_FEED2;
+
+        // Enable PLL, disconnected.
+        SC->PLL0CON = 1;
+        SC->PLL0FEED = PLLFEED_FEED1;
+        SC->PLL0FEED = PLLFEED_FEED2;
+
+        // Set clock divider.
+        SC->CCLKCFG = 0x03;
+
+        // Configure flash accelerator.
+        SC->FLASHCFG = 0x403a;
+
+        // Check lock bit status.
+        while (((SC->PLL0STAT & (1 << 26)) == 0));
+
+        // Enable and connect.
+        SC->PLL0CON = 3;
+        SC->PLL0FEED = PLLFEED_FEED1;
+        SC->PLL0FEED = PLLFEED_FEED2;
+
+        while (((SC->PLL0STAT & (1 << 25)) == 0));
+
+        // Configure the clock for the USB.
+        if (SC->PLL1STAT & (1 << 9)) {
+                // Enable PLL, disconnected.
+                SC->PLL1CON = 1;
+                SC->PLL1FEED = PLLFEED_FEED1;
+                SC->PLL1FEED = PLLFEED_FEED2;
+        }
+
+        // Disable PLL, disconnected.
+        SC->PLL1CON = 0;
+        SC->PLL1FEED = PLLFEED_FEED1;
+        SC->PLL1FEED = PLLFEED_FEED2;
+
+        SC->PLL1CFG = 0x23;
+        SC->PLL1FEED = PLLFEED_FEED1;
+        SC->PLL1FEED = PLLFEED_FEED2;
+
+        /* Enable PLL, disconnected. */
+        SC->PLL1CON = 1;
+        SC->PLL1FEED = PLLFEED_FEED1;
+        SC->PLL1FEED = PLLFEED_FEED2;
+        while (((SC->PLL1STAT & (1 << 10)) == 0));
+
+        /* Enable and connect. */
+        SC->PLL1CON = 3;
+        SC->PLL1FEED = PLLFEED_FEED1;
+        SC->PLL1FEED = PLLFEED_FEED2;
+        while (((SC->PLL1STAT & (1 << 9)) == 0));
+
+        // Setup the peripheral bus to be the same as the CCLK, 100 MHz.
+	// Set CAN to run at CCLK/6, which should have it running about 1 Mbit (1.042)
+        SC->PCLKSEL0 = 0xff555555;
+
+        /* Configure the LEDs. */
+        vParTestInitialise();
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationStackOverflowHook(xTaskHandle *pxTask, signed char *pcTaskName)
+{
+        /* This function will get called if a task overflows its stack. */
+
+        (void) pxTask;
+        (void) pcTaskName;
+
+        for (;;);
+}
+/*-----------------------------------------------------------*/
+
+void vConfigureTimerForRunTimeStats(void)
+{
+        const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;
+
+        /* This function configures a timer that is used as the time base when
+        collecting run time statistical information - basically the percentage
+        of CPU time that each task is utilising.  It is called automatically when
+        the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set
+        to 1). */
+
+        /* Power up and feed the timer. */
+        SC->PCONP |= 0x02UL;
+        SC->PCLKSEL0 = (SC->PCLKSEL0 & (~(0x3 << 2))) | (0x01 << 2);
+
+        /* Reset Timer 0 */
+        TIM0->TCR = TCR_COUNT_RESET;
+
+        /* Just count up. */
+        TIM0->CTCR = CTCR_CTM_TIMER;
+
+        /* Prescale to a frequency that is good enough to get a decent resolution,
+        but not too fast so as to overflow all the time. */
+        TIM0->PR = (configCPU_CLOCK_HZ / 10000UL) - 1UL;
+
+        /* Start the counter. */
+        TIM0->TCR = TCR_COUNT_ENABLE;
+}
+
diff --git a/gyro_board/src/usb/printf-stdarg.c b/gyro_board/src/usb/printf-stdarg.c
new file mode 100644
index 0000000..206c3db
--- /dev/null
+++ b/gyro_board/src/usb/printf-stdarg.c
@@ -0,0 +1,314 @@
+/*
+	Copyright 2001, 2002 Georges Menie (www.menie.org)
+	stdarg version contributed by Christian Ettinger
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+	putchar is the only external dependency for this file,
+	if you have a working putchar, leave it commented out.
+	If not, uncomment the define below and
+	replace outbyte(c) by your own function call.
+
+*/
+
+#include <stdarg.h>
+
+int VCOM_putchar(int c);
+
+int putchar (int c)
+{
+	return VCOM_putchar(c);
+}
+
+static void printchar(char **str, int c)
+{
+        //extern int putchar(int c);
+
+        if (str) {
+                **str = (char)c;
+                ++(*str);
+        } else {
+                VCOM_putchar(c);
+        }
+}
+
+int puts (char * str)
+{
+	int pc = 1;
+	while (*str != 0) {
+		VCOM_putchar(*str);
+		str ++;
+		pc ++;
+	}
+	VCOM_putchar('\n');
+	return pc;
+}
+
+#define PAD_RIGHT 1
+#define PAD_ZERO 2
+
+static int prints(char **out, const char *string, int width, int pad)
+{
+        register int pc = 0, padchar = ' ';
+
+        if (width > 0) {
+                register int len = 0;
+                register const char *ptr;
+                for (ptr = string; *ptr; ++ptr) ++len;
+                if (len >= width) width = 0;
+                else width -= len;
+                if (pad & PAD_ZERO) padchar = '0';
+        }
+        if (!(pad & PAD_RIGHT)) {
+                for (; width > 0; --width) {
+                        printchar(out, padchar);
+                        ++pc;
+                }
+        }
+        for (; *string ; ++string) {
+                printchar(out, *string);
+                ++pc;
+        }
+        for (; width > 0; --width) {
+                printchar(out, padchar);
+                ++pc;
+        }
+
+        return pc;
+}
+
+/* the following should be enough for 32 bit int */
+#define PRINT_BUF_LEN 12
+
+static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
+{
+        char print_buf[PRINT_BUF_LEN];
+        register char *s;
+        register int t, neg = 0, pc = 0;
+        register unsigned int u = (unsigned int)i;
+
+        if (i == 0) {
+                print_buf[0] = '0';
+                print_buf[1] = '\0';
+                return prints(out, print_buf, width, pad);
+        }
+
+        if (sg && b == 10 && i < 0) {
+                neg = 1;
+                u = (unsigned int) - i;
+        }
+
+        s = print_buf + PRINT_BUF_LEN - 1;
+        *s = '\0';
+
+        while (u) {
+                t = (unsigned int)u % b;
+                if (t >= 10)
+                        t += letbase - '0' - 10;
+                *--s = (char)(t + '0');
+                u /= b;
+        }
+
+        if (neg) {
+                if (width && (pad & PAD_ZERO)) {
+                        printchar(out, '-');
+                        ++pc;
+                        --width;
+                } else {
+                        *--s = '-';
+                }
+        }
+
+        return pc + prints(out, s, width, pad);
+}
+
+static int print(char **out, const char *format, va_list args)
+{
+        register int width, pad;
+        register int pc = 0;
+        char scr[2];
+
+        for (; *format != 0; ++format) {
+                if (*format == '%') {
+                        ++format;
+                        width = pad = 0;
+                        if (*format == '\0') break;
+                        if (*format == '%') goto pout;
+                        if (*format == '-') {
+                                ++format;
+                                pad = PAD_RIGHT;
+                        }
+                        while (*format == '0') {
+                                ++format;
+                                pad |= PAD_ZERO;
+                        }
+                        for (; *format >= '0' && *format <= '9'; ++format) {
+                                width *= 10;
+                                width += *format - '0';
+                        }
+                        if (*format == 's') {
+                                register char *s = (char *)va_arg(args, int);
+                                pc += prints(out, s ? s : "(null)", width, pad);
+                                continue;
+                        }
+                        if (*format == 'd') {
+                                pc += printi(out, va_arg(args, int), 10, 1, width, pad, 'a');
+                                continue;
+                        }
+                        if (*format == 'x') {
+                                pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'a');
+                                continue;
+                        }
+                        if (*format == 'X') {
+                                pc += printi(out, va_arg(args, int), 16, 0, width, pad, 'A');
+                                continue;
+                        }
+                        if (*format == 'u') {
+                                pc += printi(out, va_arg(args, int), 10, 0, width, pad, 'a');
+                                continue;
+                        }
+                        if (*format == 'c') {
+                                /* char are converted to int then pushed on the stack */
+                                scr[0] = (char)va_arg(args, int);
+                                scr[1] = '\0';
+                                pc += prints(out, scr, width, pad);
+                                continue;
+                        }
+                } else {
+pout:
+                        printchar(out, *format);
+                        ++pc;
+                }
+        }
+        if (out) **out = '\0';
+        va_end(args);
+        return pc;
+}
+
+int printf(const char *format, ...)
+{
+        va_list args;
+
+        va_start(args, format);
+        return print(0, format, args);
+}
+
+int sprintf(char *out, const char *format, ...)
+{
+        va_list args;
+
+        va_start(args, format);
+        return print(&out, format, args);
+}
+
+
+int snprintf(char *buf, unsigned int count, const char *format, ...)
+{
+        va_list args;
+
+        (void) count;
+
+        va_start(args, format);
+        return print(&buf, format, args);
+}
+
+
+#ifdef TEST_PRINTF
+int main(void)
+{
+        char *ptr = "Hello world!";
+        char *np = 0;
+        int i = 5;
+        unsigned int bs = sizeof(int) * 8;
+        int mi;
+        char buf[80];
+
+        mi = (1 << (bs - 1)) + 1;
+        printf("%s\n", ptr);
+        printf("printf test\n");
+        printf("%s is null pointer\n", np);
+        printf("%d = 5\n", i);
+        printf("%d = - max int\n", mi);
+        printf("char %c = 'a'\n", 'a');
+        printf("hex %x = ff\n", 0xff);
+        printf("hex %02x = 00\n", 0);
+        printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
+        printf("%d %s(s)%", 0, "message");
+        printf("\n");
+        printf("%d %s(s) with %%\n", 0, "message");
+        sprintf(buf, "justif: \"%-10s\"\n", "left");
+        printf("%s", buf);
+        sprintf(buf, "justif: \"%10s\"\n", "right");
+        printf("%s", buf);
+        sprintf(buf, " 3: %04d zero padded\n", 3);
+        printf("%s", buf);
+        sprintf(buf, " 3: %-4d left justif.\n", 3);
+        printf("%s", buf);
+        sprintf(buf, " 3: %4d right justif.\n", 3);
+        printf("%s", buf);
+        sprintf(buf, "-3: %04d zero padded\n", -3);
+        printf("%s", buf);
+        sprintf(buf, "-3: %-4d left justif.\n", -3);
+        printf("%s", buf);
+        sprintf(buf, "-3: %4d right justif.\n", -3);
+        printf("%s", buf);
+
+        return 0;
+}
+
+/*
+ * if you compile this file with
+ *   gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c
+ * you will get a normal warning:
+ *   printf.c:214: warning: spurious trailing `%' in format
+ * this line is testing an invalid % at the end of the format string.
+ *
+ * this should display (on 32bit int machine) :
+ *
+ * Hello world!
+ * printf test
+ * (null) is null pointer
+ * 5 = 5
+ * -2147483647 = - max int
+ * char a = 'a'
+ * hex ff = ff
+ * hex 00 = 00
+ * signed -3 = unsigned 4294967293 = hex fffffffd
+ * 0 message(s)
+ * 0 message(s) with %
+ * justif: "left      "
+ * justif: "     right"
+ *  3: 0003 zero padded
+ *  3: 3    left justif.
+ *  3:    3 right justif.
+ * -3: -003 zero padded
+ * -3: -3   left justif.
+ * -3:   -3 right justif.
+ */
+
+#endif
+
+
+/* To keep linker happy. */
+int	write(int i, char* c, int n)
+{
+        (void)i;
+        (void)n;
+        (void)c;
+        return 0;
+}
+
diff --git a/gyro_board/src/usb/quad encoder config.txt b/gyro_board/src/usb/quad encoder config.txt
new file mode 100644
index 0000000..4c0fe4e
--- /dev/null
+++ b/gyro_board/src/usb/quad encoder config.txt
@@ -0,0 +1,37 @@
+// Quad Encoder stuff

+

+

+// enable the quadrature encode peripheral and peripherial clock

+

+	SC->PCONP    |=0x00040000; 	// bit 18 of PCONP set to 1

+	SC->PCLKSEL1 |=0x00000001;	/* bits 1,0 	00 CCLK/4

+							01 CCLK

+							10 CCLK/2

+							11 CCLK/8  */

+

+

+// Enable pins for QEI MCI0, MCI1 (PhA PhB, signals respectively)

+

+		

+	PINCON->PINSEL3 = ((PINSEL3 &=0xFFFF3DFF) |= 0x00004100); /* 01 in bits 9:8 and 15:14*/ 

+	//PINCON->PINSEL3 = ((PINSEL3 &=0xFFFCFFFF) |= 0x00010000); /* Turns on MCI2 index input 17:16 = 01*/

+

+

+

+// Specify Quadriture phase mode

+

+	// QEI->QEICON &= 0xFFFFFFFE; 	/* Clears position counter */

+	QEI->QEICONF &= 0XFFFFFFFD;	/* Sets bit 1 to 0, Signal mode to Quad Phase */

+	// QEI->QEICON |= 0X00000002;	/* Bit 2 to 1 counts both PhA and PhB for higher resolution */

+

+

+

+	// QEI->FILTER = ****Whatever Sampling size we want*** /* Sets the number of consecutive pulses for a change in direction, etc to accepted */

+

+

+// Set Various Attributes

+

+	// QEI->QEIMAXPOS = *****insert max position*****;

+

+

+/* Note: QEI->QEIPOS is a read only section that stores the current position */
\ No newline at end of file
diff --git a/gyro_board/src/usb/spi.c b/gyro_board/src/usb/spi.c
new file mode 100644
index 0000000..de41866
--- /dev/null
+++ b/gyro_board/src/usb/spi.c
@@ -0,0 +1,60 @@
+#include "stdio.h"
+#include "FreeRTOS.h"
+#include "spi.h"
+
+void spi_init (void) {
+  SC->PCONP |= PCONP_PCSPI;
+  SC->PCLKSEL0 |= 0x00010000;
+
+  // Hook up the interrupt
+  //NVIC_EnableIRQ(SPI_IRQn);
+
+  // SCK
+  PINCON->PINSEL0 &= 0x3fffffff;
+  PINCON->PINSEL0 |= 0xc0000000;
+
+  // SSEL, MISO, MOSI
+  // SSEL is GPIO, and needs to be done manually.
+  disable_gyro_csel();
+  GPIO0->FIODIR |= 0x00010000;
+  PINCON->PINSEL1 &= 0xffffffc0;
+  PINCON->PINSEL1 |= 0x0000003c;
+
+  // Master mode, 16 bits/frame, enable interrupts
+  SPI->SPCR = 0x000000a4;
+  // 13 clocks per cycle.  This works out to a 7.7 mhz buss.
+  SPI->SPCCR = 0x0000000d;
+
+  // TODO(aschuh): Implement the gyro bring-up blocking first.
+  // Then use interrupts.
+  enable_gyro_csel();
+  printf("SPI Gyro Initial Response 0x%x %x\n", transfer_spi_bytes(0x2000), transfer_spi_bytes(0x0003));
+  disable_gyro_csel();
+}
+
+// TODO: DMA? SSP0?  SSP0 should have a buffer, which would be very nice.
+uint16_t transfer_spi_bytes(uint16_t data) {
+  SPI->SPDR = (uint32_t)data;
+  while (!(SPI->SPSR & 0x80));
+  return SPI->SPDR;
+}
+
+void disable_gyro_csel (void) {
+  // Set the CSEL pin high to deselect it.
+  GPIO0->FIOSET = 0x00010000;
+}
+
+void enable_gyro_csel (void) {
+  // Clear the CSEL pin high to select it.
+  GPIO0->FIOCLR = 0x00010000;
+}
+
+void SPI_IRQHandler(void) {
+  int status = SPI->SPSR;
+  if (status & 0x80) {
+    // Transfer completed.
+  }
+
+  // Clear the interrupt?
+  SPI->SPINT = 0x00000001;
+}
diff --git a/gyro_board/src/usb/spi.h b/gyro_board/src/usb/spi.h
new file mode 100644
index 0000000..6dbc511
--- /dev/null
+++ b/gyro_board/src/usb/spi.h
@@ -0,0 +1,9 @@
+#ifndef __SPI_H__
+#define __SPI_H__
+
+void spi_init (void);
+uint16_t transfer_spi_bytes(uint16_t data);
+void disable_gyro_csel (void);
+void enable_gyro_csel (void);
+
+#endif // __SPI_H__
diff --git a/gyro_board/src/usb/syscalls.c b/gyro_board/src/usb/syscalls.c
new file mode 100644
index 0000000..b01ad48
--- /dev/null
+++ b/gyro_board/src/usb/syscalls.c
@@ -0,0 +1,82 @@
+/* Don't need anything here. */
+
+#include <stdlib.h>
+#include <sys/stat.h>
+
+int _read_r(struct _reent *r, int file, char * ptr, int len)
+{
+        (void) r;
+        (void) file;
+        (void) ptr;
+        (void) len;
+        return -1;
+}
+
+/***************************************************************************/
+
+int _lseek_r(struct _reent *r, int file, int ptr, int dir)
+{
+        (void) r;
+        (void) file;
+        (void) ptr;
+        (void) dir;
+
+        return 0;
+}
+
+/***************************************************************************/
+
+int _write_r(struct _reent *r, int file, char * ptr, int len)
+{
+        (void) r;
+        (void) file;
+        (void) ptr;
+        (void) len;
+
+        return 0;
+}
+
+/***************************************************************************/
+
+int _close_r(struct _reent *r, int file)
+{
+        (void) r;
+        (void) file;
+
+        return 0;
+}
+
+/***************************************************************************/
+
+caddr_t _sbrk_r(struct _reent *r, int incr)
+{
+        (void) r;
+        (void) incr;
+
+        return 0;
+}
+
+/***************************************************************************/
+
+int _fstat_r(struct _reent *r, int file, struct stat * st)
+{
+        (void) r;
+        (void) file;
+        (void) st;
+
+        return 0;
+}
+
+/***************************************************************************/
+
+int _isatty_r(struct _reent *r, int fd)
+{
+        (void) r;
+        (void) fd;
+
+        return 0;
+}
+
+
+
+
diff --git a/gyro_board/src/usb/system_LPC17xx.h b/gyro_board/src/usb/system_LPC17xx.h
new file mode 100644
index 0000000..0f7d698
--- /dev/null
+++ b/gyro_board/src/usb/system_LPC17xx.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * @file:    system_LPC17xx.h
+ * @purpose: CMSIS Cortex-M3 Device Peripheral Access Layer Header File
+ *           for the NXP LPC17xx Device Series
+ * @version: V1.0
+ * @date:    25. Nov. 2008
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2008 ARM Limited. All rights reserved.
+ *
+ * ARM Limited (ARM) is supplying this software for use with Cortex-M3
+ * processor based microcontrollers.  This file can be freely distributed
+ * within development tools that are supporting such ARM based processors.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ *
+ ******************************************************************************/
+
+
+#ifndef __SYSTEM_LPC17xx_H
+#define __SYSTEM_LPC17xx_H
+
+extern uint32_t SystemFrequency;    /*!< System Clock Frequency (Core Clock)  */
+
+
+/**
+ * Initialize the system
+ *
+ * @param  none
+ * @return none
+ *
+ * @brief  Setup the microcontroller system.
+ *         Initialize the System and update the SystemFrequency variable.
+ */
+extern void SystemInit(void);
+#endif
diff --git a/gyro_board/src/usb/test.py b/gyro_board/src/usb/test.py
new file mode 100644
index 0000000..3344543
--- /dev/null
+++ b/gyro_board/src/usb/test.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+global DeviceName, AddAction, RemoveAction
+DeviceName = 'usb_device_46d_c408_noserial' # Logitech Trackball
+AddAction = 'xmodmap -e "pointer = 3 2 1 4 5 6 7 9 8"'
+RemoveAction = 'xmodmap -e "pointer = 1 2 3 4 5 6 7 8 9"'
+
+import dbus # needed to do anything
+import dbus.decorators # needed to receive messages
+import dbus.glib # needed to receive messages
+import gobject # needed to loop & monitor
+import os # needed to 
+
+def add_device(*args, **keywords):
+    Path = args[0].split('/')
+    if Path[-1] == DeviceName: # Device found
+        os.system(AddAction)
+        
+def remove_device(*args, **keywords):
+    Path = args[0].split('/')
+    if Path[-1] == DeviceName: # Device found
+        os.system(RemoveAction)
+
+bus = dbus.SystemBus()  # connect to system bus
+hal_manager_obj = bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
+hal_manager = dbus.Interface(hal_manager_obj, 'org.freedesktop.Hal.Manager')
+
+# Add listeners for all devices being added or removed
+bus.add_signal_receiver(add_device, 'DeviceAdded', 'org.freedesktop.Hal.Manager',
+                        'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
+bus.add_signal_receiver(remove_device, 'DeviceRemoved', 'org.freedesktop.Hal.Manager',
+                        'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager')
+
+# get list of all devices, determine if device is connected
+device_names = hal_manager.GetAllDevices()
+for name in device_names:
+    Path = name.split('/')
+    if Path[-1] == DeviceName: # Device found
+        os.system(AddAction)
+        break # no need to keep looking
+
+# monitor
+loop = gobject.MainLoop()
+loop.run()
diff --git a/gyro_board/src/usb/test2.py b/gyro_board/src/usb/test2.py
new file mode 100644
index 0000000..773446b
--- /dev/null
+++ b/gyro_board/src/usb/test2.py
@@ -0,0 +1,5 @@
+import pyudev
+context = pyudev.Context()
+
+devices = context.list_devices()
+print devices
diff --git a/gyro_board/src/usb_driver/90-aschuh.rules b/gyro_board/src/usb_driver/90-aschuh.rules
new file mode 100644
index 0000000..7e7699e
--- /dev/null
+++ b/gyro_board/src/usb_driver/90-aschuh.rules
@@ -0,0 +1 @@
+KERNEL=="aschuh[0-9]*",GROUP="dialout"
diff --git a/gyro_board/src/usb_driver/Makefile b/gyro_board/src/usb_driver/Makefile
new file mode 100644
index 0000000..d7f5b55
--- /dev/null
+++ b/gyro_board/src/usb_driver/Makefile
@@ -0,0 +1,8 @@
+obj-m := deploy-module.o
+deploy-module-y := usb-aschuh_can_driver.o
+
+all:
+	@make -C /lib/modules/`uname -r | tr -d '\n'`/build M=`pwd` modules
+
+clean:
+	@make -C /lib/modules/`uname -r | tr -d '\n'`/build M=`pwd` clean
diff --git a/gyro_board/src/usb_driver/README b/gyro_board/src/usb_driver/README
new file mode 100644
index 0000000..7325d87
--- /dev/null
+++ b/gyro_board/src/usb_driver/README
@@ -0,0 +1,8 @@
+To build, run 
+
+make -C /lib/modules/`uname -r | tr -d '\n'`/build M=`pwd` modules
+
+Where 2.6.38... is what you get when you run uname -r
+
+To use from a dialout user (not root)
+cp 90-aschuh.rules /etc/udev/rules.d/
diff --git a/gyro_board/src/usb_driver/aschuh_dev_cat.rb b/gyro_board/src/usb_driver/aschuh_dev_cat.rb
new file mode 100755
index 0000000..2c314d5
--- /dev/null
+++ b/gyro_board/src/usb_driver/aschuh_dev_cat.rb
@@ -0,0 +1,23 @@
+#!/usr/bin/ruby
+
+device_number = 0
+max_device_number = 1
+device = nil
+while !(device)
+	begin
+		device = File.open("/dev/aschuh#{device_number}","r+")
+	rescue
+		puts("Opening /dev/aschuh#{device_number} failed")
+		sleep(0.2)
+		device_number += 1
+		if(device_number == max_device_number)
+			device_number = 0
+		end
+	end
+end
+
+# Set the device in debug mode to view debug prints.
+device.ioctl(1,254)
+while true
+	print device.read(1)
+end
diff --git a/gyro_board/src/usb_driver/usb-aschuh_can_device.c b/gyro_board/src/usb_driver/usb-aschuh_can_device.c
new file mode 100644
index 0000000..400cc91
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_can_device.c
@@ -0,0 +1,190 @@
+#include "usb-aschuh_can_driver.h"
+#include "usb-aschuh_can_device.h"
+
+#define to_aschuh_dev(d) container_of(d, struct aschuh_dev, kref)
+static void aschuh_dev_delete(struct kref *kref)
+{
+    struct aschuh_dev *dev = to_aschuh_dev(kref);
+
+    usb_free_urb(dev->bulk.in_urb);
+	usb_free_urb(dev->intr.in_urb);
+    usb_put_dev(dev->udev);
+    kfree(dev->bulk.in_buffer);
+    kfree(dev->intr.in_buffer);
+    kfree(dev);
+}
+
+#include "usb-aschuh_fops_read.c"
+#include "usb-aschuh_fops_write.c"
+#include "usb-aschuh_fops_open.c"
+#include "usb-aschuh_fops_ioctl.c"
+#include "usb-aschuh_fops_release.c"
+
+static const struct file_operations aschuh_dev_fops = {
+	.owner =	THIS_MODULE,
+	.read  = 	aschuh_dev_read,
+	.write = 	aschuh_dev_write,
+	.open = 	aschuh_dev_open,
+	.release = 	aschuh_dev_release,
+	.flush = 	NULL,
+	.llseek = 	NULL,
+	.unlocked_ioctl = aschuh_dev_ioctl,
+};
+
+static int init_in_channel(struct aschuh_chan *chan,
+		struct usb_endpoint_descriptor *endpoint){
+    size_t buffer_size;
+    buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+    chan->in_size = buffer_size;
+    chan->in_endpointAddr = endpoint->bEndpointAddress;
+    chan->in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+    if (!chan->in_buffer) {
+        err("Could not allocate bulk_in_buffer");
+		return -1;
+    }
+    chan->in_urb = usb_alloc_urb(0, GFP_KERNEL);
+    if (!chan->in_urb) {
+        err("Could not allocate bulk_in_urb");
+		return -1;
+    }
+	return 0;
+}
+int aschuh_dev_connect_endpoints(struct aschuh_dev *dev,
+	    struct usb_host_interface *iface_desc){
+    struct usb_endpoint_descriptor *endpoint;
+    int i,rv;
+    for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+        endpoint = &iface_desc->endpoint[i].desc;
+
+        if (!dev->bulk.in_endpointAddr &&
+                usb_endpoint_is_bulk_in(endpoint)) {
+    		/* we found a bulk in endpoint */
+    		printk("ASCHUH: found_bulk_in : 0x%x \n",endpoint->bEndpointAddress);
+			if((rv = init_in_channel(&dev->bulk,endpoint)))
+				return rv;
+        }
+        if (!dev->bulk.out_endpointAddr &&
+                usb_endpoint_is_bulk_out(endpoint)) {
+            /* we found a bulk out endpoint */
+            printk("ASCHUH: found_bulk_out : 0x%x \n",endpoint->bEndpointAddress);
+            dev->bulk.out_endpointAddr = endpoint->bEndpointAddress;
+        }
+        if (!dev->intr.in_endpointAddr &&
+                usb_endpoint_is_int_in(endpoint)) {
+    		/* we found a bulk in endpoint */
+    		printk("ASCHUH: found_intr_in : 0x%x \n",endpoint->bEndpointAddress);
+			if((rv = init_in_channel(&dev->intr,endpoint)))
+				return rv;
+			dev->intr.bEndpointInterval = endpoint->bInterval;
+        }
+        if (!dev->intr.out_endpointAddr &&
+                usb_endpoint_is_int_out(endpoint)) {
+            /* we found a intr out endpoint */
+            printk("ASCHUH: found_intr_out : 0x%x \n",endpoint->bEndpointAddress);
+            dev->intr.out_endpointAddr = endpoint->bEndpointAddress;
+        }
+    }
+    if (!(dev->bulk.in_endpointAddr && dev->bulk.out_endpointAddr)) {
+        err("Could not find both bulk-in and bulk-out endpoints");
+		return -1;
+    }
+    if (!(dev->intr.in_endpointAddr && dev->intr.out_endpointAddr)) {
+        err("Could not find both intr-in and intr-out endpoints");
+		return -1;
+    }
+	return 0;
+}
+
+#define ASCHUH_DEV_MINOR_BASE 192
+//used in getting the file in /dev/
+static struct usb_class_driver aschuh_dev_class = {
+    .name =         "aschuh%d",
+    .fops =         &aschuh_dev_fops,
+    .minor_base =   ASCHUH_DEV_MINOR_BASE,
+};
+static void init_aschuh_chan(struct aschuh_chan *chan,struct aschuh_dev *dev){
+	sema_init(&chan->limit_sem, WRITES_IN_FLIGHT);
+    mutex_init(&chan->io_mutex);
+    spin_lock_init(&chan->err_lock);
+    init_completion(&chan->in_completion);
+	chan->owner = dev;
+}
+static int aschuh_can_driver_probe(struct usb_interface *interface, 
+		const struct usb_device_id *id)
+{
+	// New Drivers Show up Here!
+	struct aschuh_dev *dev;
+    int retval = -ENOMEM;
+
+    /* allocate memory for our device state and initialize it */
+    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+    if (!dev) {
+        err("Out of memory");
+        goto error;
+    }
+    kref_init(&dev->kref);
+	
+    init_usb_anchor(&dev->submitted);
+	init_aschuh_chan(&dev->bulk,dev);
+	init_aschuh_chan(&dev->intr,dev);
+
+
+    dev->udev = usb_get_dev(interface_to_usbdev(interface));
+    dev->interface = interface;
+
+    /* set up the endpoint information */
+    /* use only the first bulk-in and bulk-out endpoints */
+	if(aschuh_dev_connect_endpoints(dev,interface->cur_altsetting))
+		goto error;
+
+    /* save our data pointer in this interface device */
+    usb_set_intfdata(interface, dev);
+
+    /* we can register the device now, as it is ready */
+    retval = usb_register_dev(interface, &aschuh_dev_class);
+    if (retval) {
+        /* something prevented us from registering this driver */
+        err("Not able to get a minor for this device.");
+        usb_set_intfdata(interface, NULL);
+        goto error;
+    }
+
+	printk("CAN driver has been probed - %d\n",interface->minor);
+    /* let the user know what node this device is now attached to */
+    dev_info(&interface->dev,
+            "USB aschuh_dev device now attached to USB_ASCHUH-%d",
+            interface->minor);
+    return 0;
+
+error:
+    if (dev)
+        /* this frees allocated memory */
+        kref_put(&dev->kref, aschuh_dev_delete);
+	return -ENOMEM;
+}
+static void aschuh_can_driver_disconnect(struct usb_interface *interface)
+{
+    struct aschuh_dev *dev;
+    int minor = interface->minor;
+
+    dev = usb_get_intfdata(interface);
+    usb_set_intfdata(interface, NULL);
+
+    /* give back our minor */
+    usb_deregister_dev(interface, &aschuh_dev_class);
+
+    /* prevent more I/O from starting */
+	mutex_lock(&dev->bulk.io_mutex);
+	mutex_lock(&dev->intr.io_mutex);
+    dev->interface = NULL;
+    mutex_unlock(&dev->bulk.io_mutex);
+    mutex_unlock(&dev->intr.io_mutex);
+
+    usb_kill_anchored_urbs(&dev->submitted);
+
+    /* decrement our usage count */
+    kref_put(&dev->kref, aschuh_dev_delete);
+
+    dev_info(&interface->dev, "USB aschuh_dev #%d now disconnected", minor);
+}
+
diff --git a/gyro_board/src/usb_driver/usb-aschuh_can_device.h b/gyro_board/src/usb_driver/usb-aschuh_can_device.h
new file mode 100644
index 0000000..0065839
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_can_device.h
@@ -0,0 +1,37 @@
+#ifndef _USB_ASCHUH_CAN_DEVICE__H_
+#define _USB_ASCHUH_CAN_DEVICE__H_
+struct aschuh_dev;
+struct aschuh_chan{
+    struct urb              *in_urb;           /* the urb to read data with */
+    unsigned char           *in_buffer;        /* the buffer to receive data */
+    size_t                  in_size;           /* the size of the receive buffer */
+    size_t                  in_filled;         /* number of bytes in the buffer */
+    size_t                  in_copied;         /* already copied to user space */
+    __u8                    in_endpointAddr;   /* the address of the in endpoint */
+    __u8                    out_endpointAddr;  /* the address of the out endpoint */
+    int                     errors;            /* the last request tanked */
+    spinlock_t              err_lock;          /* lock for errors */
+    struct mutex            io_mutex;          /* synchronize I/O with disconnect */
+    struct semaphore        limit_sem;              /* limiting the number of writes in progress */
+    struct completion       in_completion;     /* to wait for an ongoing read */
+    bool                    ongoing_read;      /* a read is going on */
+    bool                    processed_urb;     /* indicates we haven't processed the urb */
+	__u8					bEndpointInterval; /* used in fill_int_urb */
+	struct aschuh_dev		*owner;
+};
+
+struct aschuh_dev{
+    struct usb_device       *udev;                  /* the usb device for this device */
+    struct usb_interface    *interface;             /* the interface for this device */
+    struct usb_anchor       submitted;              /* in case we need to retract our submissions */
+	struct aschuh_chan		bulk;					/* channel for handling bulk requests */
+	struct aschuh_chan		intr;
+    int                     open_count;             /* count the number of openers */
+    struct kref             kref;
+};
+static void aschuh_can_driver_disconnect(struct usb_interface *interface);
+static int aschuh_can_driver_probe(struct usb_interface *interface,
+        const struct usb_device_id *id);
+
+
+#endif
diff --git a/gyro_board/src/usb_driver/usb-aschuh_can_driver.c b/gyro_board/src/usb_driver/usb-aschuh_can_driver.c
new file mode 100644
index 0000000..44a7f6e
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_can_driver.c
@@ -0,0 +1,46 @@
+#include "usb-aschuh_can_driver.h"
+#include "usb-aschuh_can_device.h"
+#define WRITES_IN_FLIGHT        8
+static const struct usb_device_id aschuh_can_device_table[] = {
+	{ USB_DEVICE(VENDOR_ID,	PRODUCT_ID) },
+	{ } /*terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, aschuh_can_device_table);
+
+
+#include "usb-aschuh_can_device.c"
+static struct usb_driver aschuh_can_driver = {
+	.name = 	"aschuh_can_driver",
+	.probe =  	aschuh_can_driver_probe,
+	.disconnect = 	aschuh_can_driver_disconnect,
+	.suspend =	NULL,
+	.resume =	NULL,
+	.pre_reset = 	NULL,
+	.post_reset = 	NULL,
+	.id_table = 	aschuh_can_device_table,
+	.supports_autosuspend = 0,
+};
+
+static int __init aschuh_can_driver_init(void)
+{
+	int result;
+
+	result = usb_register(&aschuh_can_driver);
+	if(result)
+		err("usb_register failed. Error number %d",result);
+
+	printk("INIT CAN driver\n");
+	return result;
+}
+static void __exit aschuh_can_driver_exit(void)
+{
+	usb_deregister(&aschuh_can_driver);
+	printk("Closing CAN driver\n");
+}
+
+
+module_init(aschuh_can_driver_init);
+module_exit(aschuh_can_driver_exit);
+
+
+MODULE_LICENSE("GPL"); //not sure about this.
diff --git a/gyro_board/src/usb_driver/usb-aschuh_can_driver.h b/gyro_board/src/usb_driver/usb-aschuh_can_driver.h
new file mode 100644
index 0000000..73fcb1f
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_can_driver.h
@@ -0,0 +1,21 @@
+#ifndef __USB_ASCHUH_CAN_DRIVER__H_
+#define __USB_ASCHUH_CAN_DRIVER__H_
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+
+struct aschuh_can_device {
+	struct usb_device	*udev;
+	struct usb_interface	*interface;
+};
+#define VENDOR_ID		0x1424
+#define PRODUCT_ID		0xd243
+
+#endif
diff --git a/gyro_board/src/usb_driver/usb-aschuh_fops_ioctl.c b/gyro_board/src/usb_driver/usb-aschuh_fops_ioctl.c
new file mode 100644
index 0000000..4229444
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_fops_ioctl.c
@@ -0,0 +1,19 @@
+static long aschuh_dev_ioctl(struct file *file,
+		unsigned int cmd, unsigned long arg)
+{
+	struct aschuh_chan *new_chan;
+	struct aschuh_chan *chan = file->private_data;
+	struct aschuh_dev *dev = chan->owner;
+	printk("ioctl(%d,%d)\n",cmd,(int)arg);
+	if(cmd == 1){
+		if(arg == 254){
+			new_chan = &dev->bulk;
+		}else{
+			new_chan = &dev->intr;
+		}
+		file->private_data = new_chan;
+		return 0;
+	}else{
+		return 0;
+	}
+}
diff --git a/gyro_board/src/usb_driver/usb-aschuh_fops_open.c b/gyro_board/src/usb_driver/usb-aschuh_fops_open.c
new file mode 100644
index 0000000..5263acd
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_fops_open.c
@@ -0,0 +1,60 @@
+static struct usb_driver aschuh_can_driver;
+static int aschuh_dev_open(struct inode *inode, struct file *file)
+{
+    struct aschuh_dev *dev;
+    struct usb_interface *interface;
+    int subminor;
+
+    subminor = iminor(inode);
+	printk("opening device!!!\n");
+    interface = usb_find_interface(&aschuh_can_driver, subminor);
+    if (!interface) {
+        err("%s - error, can't find device for minor %d",
+                __func__, subminor);
+        return( -ENODEV);
+    }
+
+    dev = usb_get_intfdata(interface);
+    if (!dev) {
+        return( -ENODEV);
+    }
+
+    /* increment our usage count for the device */
+    kref_get(&dev->kref);
+
+    /* lock the device to allow correctly handling errors
+     * in resumption */
+    mutex_lock(&dev->bulk.io_mutex);
+    mutex_lock(&dev->intr.io_mutex);
+	//TODO(parker): Hey folks! I just commented this out.
+	// it would be a good thing to check what usb_autopm_get_interface
+	// actually does :P. Good thing to check if you find errors.
+	/*
+    if (!dev->open_count++) {
+        int retval = usb_autopm_get_interface(interface);
+        if (retval) {
+            dev->open_count--;
+            mutex_unlock(&dev->bulk.io_mutex);
+            mutex_unlock(&dev->intr.io_mutex);
+            kref_put(&dev->kref, aschuh_dev_delete);
+            return retval;
+        }
+    }
+	*/
+	/* else { //uncomment this block if you want exclusive open
+         retval = -EBUSY;
+         dev->open_count--;
+         mutex_unlock(&dev->io_mutex);
+         kref_put(&dev->kref, aschuh_dev_delete);
+         goto exit;
+         } */
+    /* prevent the device from being autosuspended */
+
+    /* save our object in the file's private structure */
+    file->private_data = &dev->intr;
+    mutex_unlock(&dev->bulk.io_mutex);
+    mutex_unlock(&dev->intr.io_mutex);
+
+    return 0;
+}
+
diff --git a/gyro_board/src/usb_driver/usb-aschuh_fops_read.c b/gyro_board/src/usb_driver/usb-aschuh_fops_read.c
new file mode 100644
index 0000000..912e4b6
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_fops_read.c
@@ -0,0 +1,207 @@
+static void aschuh_chan_read_callback(struct urb *urb)
+{
+    struct aschuh_chan *chan;
+
+    chan = urb->context;
+
+    spin_lock(&chan->err_lock);
+    /* sync/async unlink faults aren't errors */
+    if (urb->status) {
+        if (!(urb->status == -ENOENT ||
+                    urb->status == -ECONNRESET ||
+                    urb->status == -ESHUTDOWN))
+            err("%s - nonzero write bulk status received: %d",
+                    __func__, urb->status);
+
+        chan->errors = urb->status;
+    } else {
+        chan->in_filled = urb->actual_length;
+    }
+    chan->ongoing_read = 0;
+    spin_unlock(&chan->err_lock);
+
+    complete(&chan->in_completion);
+}
+
+static int aschuh_chan_submit(struct aschuh_chan *chan){
+    int rv;
+    /* tell everybody to leave the URB alone */
+    spin_lock_irq(&chan->err_lock);
+    chan->ongoing_read = 1;
+    spin_unlock_irq(&chan->err_lock);
+	
+
+    /* do it */
+    rv = usb_submit_urb(chan->in_urb, GFP_KERNEL);
+    if (rv < 0) {
+        err("%s - failed submitting read urb, error %d",
+                __func__, rv);
+        chan->in_filled = 0;
+        rv = (rv == -ENOMEM) ? rv : -EIO;
+        spin_lock_irq(&chan->err_lock);
+        chan->ongoing_read = 0;
+        spin_unlock_irq(&chan->err_lock);
+    }
+
+    return rv;
+}
+
+
+static int aschuh_dev_bulk_do_read_io(struct aschuh_dev *dev,size_t count)
+{
+	struct aschuh_chan *chan = &dev->bulk;
+    /* prepare a read */
+    usb_fill_bulk_urb(chan->in_urb, dev->udev,
+            usb_rcvbulkpipe(dev->udev, chan->in_endpointAddr),
+            chan->in_buffer,
+            min(chan->in_size, count),
+            aschuh_chan_read_callback,
+            chan);
+	return aschuh_chan_submit(chan);
+}
+
+static int aschuh_dev_intr_do_read_io(struct aschuh_dev *dev,size_t count)
+{
+	struct aschuh_chan *chan = &dev->intr;
+    /* prepare a read */
+    usb_fill_int_urb(chan->in_urb, dev->udev,
+            usb_rcvintpipe(dev->udev, chan->in_endpointAddr),
+            chan->in_buffer,
+            chan->in_size,
+            aschuh_chan_read_callback,
+            chan,chan->bEndpointInterval);
+	return aschuh_chan_submit(chan);
+}
+
+static ssize_t aschuh_dev_read(struct file *file, char *buffer, size_t count,
+        loff_t *ppos)
+{
+	int rv;
+	bool ongoing_io;
+	struct aschuh_chan *chan = file->private_data;
+	struct aschuh_dev *dev = chan->owner; 
+	enum chan_types{
+		BULK_CHAN, INTR_CHAN
+	} chan_type = INTR_CHAN;
+    size_t available;
+	if(chan == &dev->intr)
+		chan_type = INTR_CHAN;
+	else if(chan == &dev->bulk){
+		chan_type = BULK_CHAN;
+	}else{
+		printk("Chan type not debug or data!!!");
+		return 0;
+	}
+	
+
+	    /* if we cannot read at all, return EOF */
+    if (!chan->in_urb || !count)
+        return 0;
+
+	rv = mutex_lock_interruptible(&chan->io_mutex);
+    if (rv < 0)
+        return rv;
+
+	if (!dev->interface) {          /* disconnect() was called */
+        rv = -ENODEV;
+        goto exit;
+    }
+
+	    /* if IO is under way, we must not touch things */
+	while(true){
+    	spin_lock_irq(&chan->err_lock);
+    	ongoing_io = chan->ongoing_read;
+    	spin_unlock_irq(&chan->err_lock);
+
+    	if (ongoing_io) {
+        	/* nonblocking IO shall not wait */
+        	if (file->f_flags & O_NONBLOCK) {
+            	rv = -EAGAIN;
+            	goto exit;
+        	}
+        	/*
+         	 * IO may take forever
+         	 * hence wait in an interruptible state
+         	 */
+			mutex_unlock(&chan->io_mutex);
+        	rv = wait_for_completion_interruptible(&chan->in_completion);
+        	if (rv < 0)
+            	return rv;
+
+			rv = mutex_lock_interruptible(&chan->io_mutex);
+    		if (rv < 0)
+        		return rv;
+        	/*
+         	 * by waiting we also semiprocessed the urb
+         	 * we must finish now
+         	 */
+        	chan->in_copied = 0;
+    	}
+
+
+    	/* errors must be reported */
+    	rv = chan->errors;
+    	if (rv < 0) {
+        	/* any error is reported once */
+        	chan->errors = 0;
+        	/* to preserve notifications about reset */
+        	rv = (rv == -EPIPE) ? rv : -EIO;
+        	/* no data to deliver */
+        	chan->in_filled = 0;
+        	/* report it */
+        	goto exit;
+    	}
+		/*
+     	 * if the buffer is filled we may satisfy the read
+     	 * else we need to start IO
+     	 */
+
+    	/* we had read data */
+    	available = chan->in_filled - chan->in_copied;
+
+    	if (!chan->in_filled || !available) {
+        	/*
+         	 * all data has been used or no data is avaiable.
+         	 * actual IO needs to be done
+         	 */
+			if(chan_type == INTR_CHAN)
+        		rv = aschuh_dev_intr_do_read_io(dev, count);
+			else if(chan_type == BULK_CHAN){
+        		rv = aschuh_dev_bulk_do_read_io(dev, count);
+			}
+        	if (rv < 0)
+            	goto exit;
+    	}else{
+    		size_t chunk = min(available, count);
+    		/*
+     	 	 * data is available
+     	 	 * chunk tells us how much shall be copied
+     	 	 */
+
+    		if (copy_to_user(buffer,
+                		chan->in_buffer + chan->in_copied,
+                		chunk))
+        		rv = -EFAULT;
+    		else
+        		rv = chunk;
+
+    		chan->in_copied += chunk;
+
+    		/*
+     	 	 * if we are asked for more than we have,
+     	 	 * we start IO but don't wait
+     	 	 */
+    		//if (available < count){
+			//	if(chan_type == INTR_CHAN)
+        	//		aschuh_dev_intr_do_read_io(dev, count);
+			//	else if(chan_type == BULK_CHAN){
+        	//		aschuh_dev_bulk_do_read_io(dev, count);
+			//	}
+			//}
+			goto exit;
+		}
+	}
+exit:
+	mutex_unlock(&chan->io_mutex);
+	return rv;
+}
diff --git a/gyro_board/src/usb_driver/usb-aschuh_fops_release.c b/gyro_board/src/usb_driver/usb-aschuh_fops_release.c
new file mode 100644
index 0000000..259a1b9
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_fops_release.c
@@ -0,0 +1,22 @@
+static int aschuh_dev_release(struct inode *inode, struct file *file)
+{
+    struct aschuh_dev *dev;
+	printk("closing device!!!\n");
+
+    dev = ((struct aschuh_chan *)file->private_data)->owner;
+    if (dev == NULL)
+        return -ENODEV;
+
+    /* allow the device to be autosuspended */
+   	//mutex_lock(&dev->bulk.io_mutex);
+    //mutex_lock(&dev->intr.io_mutex);
+    //if (!--dev->open_count && dev->interface)
+    //    usb_autopm_put_interface(dev->interface);
+    //mutex_unlock(&dev->bulk.io_mutex);
+    //mutex_unlock(&dev->intr.io_mutex);
+
+    /* decrement the count on our device */
+    kref_put(&dev->kref, aschuh_dev_delete);
+    return 0;
+}
+
diff --git a/gyro_board/src/usb_driver/usb-aschuh_fops_write.c b/gyro_board/src/usb_driver/usb-aschuh_fops_write.c
new file mode 100644
index 0000000..7a9e00e
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-aschuh_fops_write.c
@@ -0,0 +1,144 @@
+#include <linux/usb.h>
+static void aschuh_dev_write_callback(struct urb *urb)
+{
+    struct aschuh_chan *chan;
+
+    chan = urb->context;
+    /* sync/async unlink faults aren't errors */
+    if (urb->status) {
+        if (!(urb->status == -ENOENT ||
+                    urb->status == -ECONNRESET ||
+                    urb->status == -ESHUTDOWN))
+            err("%s - nonzero write bulk status received: %d",
+                    __func__, urb->status);
+
+        spin_lock(&chan->err_lock);
+        chan->errors = urb->status;
+        spin_unlock(&chan->err_lock);
+    }
+
+    /* free up our allocated buffer */
+    usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+            urb->transfer_buffer, urb->transfer_dma);
+    up(&chan->limit_sem);
+}
+//#define WRITES_IN_FLIGHT        8
+#define MAX_TRANSFER	64
+
+static ssize_t aschuh_dev_write(struct file *file, const char *user_buffer,
+        size_t count, loff_t *ppos)
+{
+    struct aschuh_chan *chan;
+	struct aschuh_dev *dev;
+    int retval = 0;
+    struct urb *urb = NULL;
+    char *buf = NULL;
+    size_t writesize = min(count, (size_t)MAX_TRANSFER);
+
+    chan = file->private_data;
+	dev = chan->owner;
+
+    /* verify that we actually have some data to write */
+    if (count == 0)
+        goto exit;
+
+    /*
+     * limit the number of URBs in flight to stop a user from using up all
+     * RAM
+     */
+    if (!(file->f_flags & O_NONBLOCK)) {
+        if (down_interruptible(&chan->limit_sem)) {
+            retval = -ERESTARTSYS;
+            goto exit;
+        }
+    } else {
+        if (down_trylock(&chan->limit_sem)) {
+            retval = -EAGAIN;
+            goto exit;
+        }
+    }
+
+    spin_lock_irq(&chan->err_lock);
+    retval = chan->errors;
+    if (retval < 0) {
+        /* any error is reported once */
+        chan->errors = 0;
+        /* to preserve notifications about reset */
+        retval = (retval == -EPIPE) ? retval : -EIO;
+    }
+    spin_unlock_irq(&chan->err_lock);
+    if (retval < 0)
+        goto error;
+
+    /* create a urb, and a buffer for it, and copy the data to the urb */
+    urb = usb_alloc_urb(0, GFP_KERNEL);
+    if (!urb) {
+        retval = -ENOMEM;
+        goto error;
+    }
+
+    buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL,
+            &urb->transfer_dma);
+    if (!buf) {
+        retval = -ENOMEM;
+        goto error;
+    }
+
+    if (copy_from_user(buf, user_buffer, writesize)) {
+        retval = -EFAULT;
+        goto error;
+    }
+
+    /* this lock makes sure we don't submit URBs to gone devices */
+    mutex_lock(&chan->io_mutex);
+    if (!dev->interface) {          /* disconnect() was called */
+        mutex_unlock(&chan->io_mutex);
+		printk("Should be exiting shortly.... stay tuned for details\n");
+        retval = -ENODEV;
+        goto error;
+    }
+
+    /* initialize the urb properly */
+	if(chan == &dev->bulk){
+    	usb_fill_bulk_urb(urb, dev->udev,
+            usb_sndbulkpipe(dev->udev, chan->out_endpointAddr),
+            buf, writesize, aschuh_dev_write_callback, chan);
+	}else{
+		usb_fill_int_urb(urb, dev->udev,
+            usb_sndintpipe(dev->udev, chan->out_endpointAddr),
+            buf, writesize, aschuh_dev_write_callback, chan,
+			chan->bEndpointInterval);
+	}
+    urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+    usb_anchor_urb(urb, &dev->submitted);
+    /* send the data out the bulk port */
+    retval = usb_submit_urb(urb, GFP_KERNEL);
+    mutex_unlock(&chan->io_mutex);
+    if (retval) {
+        err("%s - failed submitting write urb, error %d", __func__,
+                retval);
+    	usb_unanchor_urb(urb);
+		goto error;
+    }
+
+    /*
+     * release our reference to this urb, the USB core will eventually free
+     * it entirely
+     */
+    usb_free_urb(urb);
+
+
+    return writesize;
+
+error:
+    if (urb) {
+        usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma);
+        usb_free_urb(urb);
+    }
+    up(&chan->limit_sem);
+
+exit:
+    return retval;
+}
+
diff --git a/gyro_board/src/usb_driver/usb-skeleton.c b/gyro_board/src/usb_driver/usb-skeleton.c
new file mode 100644
index 0000000..1409724
--- /dev/null
+++ b/gyro_board/src/usb_driver/usb-skeleton.c
@@ -0,0 +1,713 @@
+/*
+ * USB Skeleton driver - 2.2
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation, version 2.
+ *
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c
+ * but has been rewritten to be easier to read and use.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+
+
+/* Define these values to match your devices */
+#define USB_SKEL_VENDOR_ID      0xfff0
+#define USB_SKEL_PRODUCT_ID     0xfff0
+
+/* table of devices that work with this driver */
+static const struct usb_device_id skel_table[] = {
+    { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
+    { }                                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, skel_table);
+
+
+/* Get a minor range for your devices from the usb maintainer */
+#define USB_SKEL_MINOR_BASE     192
+
+/* our private defines. if this grows any larger, use your own .h file */
+#define MAX_TRANSFER            (PAGE_SIZE - 512)
+/* MAX_TRANSFER is chosen so that the VM is not stressed by
+   allocations > PAGE_SIZE and the number of packets in a page
+   is an integer 512 is the largest possible packet on EHCI */
+#define WRITES_IN_FLIGHT        8
+/* arbitrarily chosen */
+
+/* Structure to hold all of our device specific stuff */
+struct usb_skel {
+    struct usb_device       *udev;                  /* the usb device for this device */
+    struct usb_interface    *interface;             /* the interface for this device */
+    struct semaphore        limit_sem;              /* limiting the number of writes in progress */
+    struct usb_anchor       submitted;              /* in case we need to retract our submissions */
+    struct urb              *bulk_in_urb;           /* the urb to read data with */
+    unsigned char           *bulk_in_buffer;        /* the buffer to receive data */
+    size_t                  bulk_in_size;           /* the size of the receive buffer */
+    size_t                  bulk_in_filled;         /* number of bytes in the buffer */
+    size_t                  bulk_in_copied;         /* already copied to user space */
+    __u8                    bulk_in_endpointAddr;   /* the address of the bulk in endpoint */
+    __u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
+    int                     errors;                 /* the last request tanked */
+    int                     open_count;             /* count the number of openers */
+    bool                    ongoing_read;           /* a read is going on */
+    bool                    processed_urb;          /* indicates we haven't processed the urb */
+    spinlock_t              err_lock;               /* lock for errors */
+    struct kref             kref;
+    struct mutex            io_mutex;               /* synchronize I/O with disconnect */
+    struct completion       bulk_in_completion;     /* to wait for an ongoing read */
+};
+#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
+
+static struct usb_driver skel_driver;
+static void skel_draw_down(struct usb_skel *dev);
+
+static void skel_delete(struct kref *kref)
+{
+    struct usb_skel *dev = to_skel_dev(kref);
+
+    usb_free_urb(dev->bulk_in_urb);
+    usb_put_dev(dev->udev);
+    kfree(dev->bulk_in_buffer);
+    kfree(dev);
+}
+
+static int skel_open(struct inode *inode, struct file *file)
+{
+    struct usb_skel *dev;
+    struct usb_interface *interface;
+    int subminor;
+    int retval = 0;
+
+    subminor = iminor(inode);
+
+    interface = usb_find_interface(&skel_driver, subminor);
+    if (!interface) {
+        err("%s - error, can't find device for minor %d",
+                __func__, subminor);
+        retval = -ENODEV;
+        goto exit;
+    }
+
+    dev = usb_get_intfdata(interface);
+    if (!dev) {
+        retval = -ENODEV;
+        goto exit;
+    }
+
+    /* increment our usage count for the device */
+    kref_get(&dev->kref);
+
+    /* lock the device to allow correctly handling errors
+     * in resumption */
+    mutex_lock(&dev->io_mutex);
+
+    if (!dev->open_count++) {
+        retval = usb_autopm_get_interface(interface);
+        if (retval) {
+            dev->open_count--;
+            mutex_unlock(&dev->io_mutex);
+            kref_put(&dev->kref, skel_delete);
+            goto exit;
+        }
+    } /* else { //uncomment this block if you want exclusive open
+         retval = -EBUSY;
+         dev->open_count--;
+         mutex_unlock(&dev->io_mutex);
+         kref_put(&dev->kref, skel_delete);
+         goto exit;
+         } */
+    /* prevent the device from being autosuspended */
+
+    /* save our object in the file's private structure */
+    file->private_data = dev;
+    mutex_unlock(&dev->io_mutex);
+
+exit:
+    return retval;
+}
+
+static int skel_release(struct inode *inode, struct file *file)
+{
+    struct usb_skel *dev;
+
+    dev = file->private_data;
+    if (dev == NULL)
+        return -ENODEV;
+
+    /* allow the device to be autosuspended */
+    mutex_lock(&dev->io_mutex);
+    if (!--dev->open_count && dev->interface)
+        usb_autopm_put_interface(dev->interface);
+    mutex_unlock(&dev->io_mutex);
+
+    /* decrement the count on our device */
+    kref_put(&dev->kref, skel_delete);
+    return 0;
+}
+
+static int skel_flush(struct file *file, fl_owner_t id)
+{
+    struct usb_skel *dev;
+    int res;
+
+    dev = file->private_data;
+    if (dev == NULL)
+        return -ENODEV;
+
+    /* wait for io to stop */
+    mutex_lock(&dev->io_mutex);
+    skel_draw_down(dev);
+
+    /* read out errors, leave subsequent opens a clean slate */
+    spin_lock_irq(&dev->err_lock);
+    res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0;
+    dev->errors = 0;
+    spin_unlock_irq(&dev->err_lock);
+
+    mutex_unlock(&dev->io_mutex);
+
+    return res;
+}
+
+static void skel_read_bulk_callback(struct urb *urb)
+{
+    struct usb_skel *dev;
+
+    dev = urb->context;
+
+    spin_lock(&dev->err_lock);
+    /* sync/async unlink faults aren't errors */
+    if (urb->status) {
+        if (!(urb->status == -ENOENT ||
+                    urb->status == -ECONNRESET ||
+                    urb->status == -ESHUTDOWN))
+            err("%s - nonzero write bulk status received: %d",
+                    __func__, urb->status);
+
+        dev->errors = urb->status;
+    } else {
+        dev->bulk_in_filled = urb->actual_length;
+    }
+    dev->ongoing_read = 0;
+    spin_unlock(&dev->err_lock);
+
+    complete(&dev->bulk_in_completion);
+}
+
+static int skel_do_read_io(struct usb_skel *dev, size_t count)
+{
+    int rv;
+
+    /* prepare a read */
+    usb_fill_bulk_urb(dev->bulk_in_urb,
+            dev->udev,
+            usb_rcvbulkpipe(dev->udev,
+                dev->bulk_in_endpointAddr),
+            dev->bulk_in_buffer,
+            min(dev->bulk_in_size, count),
+            skel_read_bulk_callback,
+            dev);
+    /* tell everybody to leave the URB alone */
+    spin_lock_irq(&dev->err_lock);
+    dev->ongoing_read = 1;
+    spin_unlock_irq(&dev->err_lock);
+
+    /* do it */
+    rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
+    if (rv < 0) {
+        err("%s - failed submitting read urb, error %d",
+                __func__, rv);
+        dev->bulk_in_filled = 0;
+        rv = (rv == -ENOMEM) ? rv : -EIO;
+        spin_lock_irq(&dev->err_lock);
+        dev->ongoing_read = 0;
+        spin_unlock_irq(&dev->err_lock);
+    }
+
+    return rv;
+}
+
+static ssize_t skel_read(struct file *file, char *buffer, size_t count,
+        loff_t *ppos)
+{
+    struct usb_skel *dev;
+    int rv;
+    bool ongoing_io;
+
+    dev = file->private_data;
+
+    /* if we cannot read at all, return EOF */
+    if (!dev->bulk_in_urb || !count)
+        return 0;
+
+    /* no concurrent readers */
+    rv = mutex_lock_interruptible(&dev->io_mutex);
+    if (rv < 0)
+        return rv;
+
+    if (!dev->interface) {          /* disconnect() was called */
+        rv = -ENODEV;
+        goto exit;
+    }
+
+    /* if IO is under way, we must not touch things */
+retry:
+    spin_lock_irq(&dev->err_lock);
+    ongoing_io = dev->ongoing_read;
+    spin_unlock_irq(&dev->err_lock);
+
+    if (ongoing_io) {
+        /* nonblocking IO shall not wait */
+        if (file->f_flags & O_NONBLOCK) {
+            rv = -EAGAIN;
+            goto exit;
+        }
+        /*
+         * IO may take forever
+         * hence wait in an interruptible state
+         */
+        rv = wait_for_completion_interruptible(&dev->bulk_in_completion);
+        if (rv < 0)
+            goto exit;
+        /*
+         * by waiting we also semiprocessed the urb
+         * we must finish now
+         */
+        dev->bulk_in_copied = 0;
+        dev->processed_urb = 1;
+    }
+
+    if (!dev->processed_urb) {
+        /*
+         * the URB hasn't been processed
+         * do it now
+         */
+        wait_for_completion(&dev->bulk_in_completion);
+        dev->bulk_in_copied = 0;
+        dev->processed_urb = 1;
+    }
+
+    /* errors must be reported */
+    rv = dev->errors;
+    if (rv < 0) {
+        /* any error is reported once */
+        dev->errors = 0;
+        /* to preserve notifications about reset */
+        rv = (rv == -EPIPE) ? rv : -EIO;
+        /* no data to deliver */
+        dev->bulk_in_filled = 0;
+        /* report it */
+        goto exit;
+    }
+
+    /*
+     * if the buffer is filled we may satisfy the read
+     * else we need to start IO
+     */
+
+    if (dev->bulk_in_filled) {
+        /* we had read data */
+        size_t available = dev->bulk_in_filled - dev->bulk_in_copied;
+        size_t chunk = min(available, count);
+
+        if (!available) {
+            /*
+             * all data has been used
+             * actual IO needs to be done
+             */
+            rv = skel_do_read_io(dev, count);
+            if (rv < 0)
+                goto exit;
+            else
+                goto retry;
+        }
+        /*
+         * data is available
+         * chunk tells us how much shall be copied
+         */
+
+        if (copy_to_user(buffer,
+                    dev->bulk_in_buffer + dev->bulk_in_copied,
+                    chunk))
+            rv = -EFAULT;
+        else
+            rv = chunk;
+
+        dev->bulk_in_copied += chunk;
+
+        /*
+         * if we are asked for more than we have,
+         * we start IO but don't wait
+         */
+        if (available < count)
+            skel_do_read_io(dev, count - chunk);
+    } else {
+        /* no data in the buffer */
+        rv = skel_do_read_io(dev, count);
+        if (rv < 0)
+            goto exit;
+        else if (!(file->f_flags & O_NONBLOCK))
+            goto retry;
+        rv = -EAGAIN;
+    }
+exit:
+    mutex_unlock(&dev->io_mutex);
+    return rv;
+}
+
+static void skel_write_bulk_callback(struct urb *urb)
+{
+    struct usb_skel *dev;
+
+    dev = urb->context;
+
+    /* sync/async unlink faults aren't errors */
+    if (urb->status) {
+        if (!(urb->status == -ENOENT ||
+                    urb->status == -ECONNRESET ||
+                    urb->status == -ESHUTDOWN))
+            err("%s - nonzero write bulk status received: %d",
+                    __func__, urb->status);
+
+        spin_lock(&dev->err_lock);
+        dev->errors = urb->status;
+        spin_unlock(&dev->err_lock);
+    }
+
+    /* free up our allocated buffer */
+    usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+            urb->transfer_buffer, urb->transfer_dma);
+    up(&dev->limit_sem);
+}
+
+static ssize_t skel_write(struct file *file, const char *user_buffer,
+        size_t count, loff_t *ppos)
+{
+    struct usb_skel *dev;
+    int retval = 0;
+    struct urb *urb = NULL;
+    char *buf = NULL;
+    size_t writesize = min(count, (size_t)MAX_TRANSFER);
+
+    dev = file->private_data;
+
+    /* verify that we actually have some data to write */
+    if (count == 0)
+        goto exit;
+
+    /*
+     * limit the number of URBs in flight to stop a user from using up all
+     * RAM
+     */
+    if (!(file->f_flags & O_NONBLOCK)) {
+        if (down_interruptible(&dev->limit_sem)) {
+            retval = -ERESTARTSYS;
+            goto exit;
+        }
+    } else {
+        if (down_trylock(&dev->limit_sem)) {
+            retval = -EAGAIN;
+            goto exit;
+        }
+    }
+
+    spin_lock_irq(&dev->err_lock);
+    retval = dev->errors;
+    if (retval < 0) {
+        /* any error is reported once */
+        dev->errors = 0;
+        /* to preserve notifications about reset */
+        retval = (retval == -EPIPE) ? retval : -EIO;
+    }
+    spin_unlock_irq(&dev->err_lock);
+    if (retval < 0)
+        goto error;
+
+    /* create a urb, and a buffer for it, and copy the data to the urb */
+    urb = usb_alloc_urb(0, GFP_KERNEL);
+    if (!urb) {
+        retval = -ENOMEM;
+        goto error;
+    }
+
+    buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL,
+            &urb->transfer_dma);
+    if (!buf) {
+        retval = -ENOMEM;
+        goto error;
+    }
+
+    if (copy_from_user(buf, user_buffer, writesize)) {
+        retval = -EFAULT;
+        goto error;
+    }
+
+    /* this lock makes sure we don't submit URBs to gone devices */
+    mutex_lock(&dev->io_mutex);
+    if (!dev->interface) {          /* disconnect() was called */
+        mutex_unlock(&dev->io_mutex);
+        retval = -ENODEV;
+        goto error;
+    }
+
+    /* initialize the urb properly */
+    usb_fill_bulk_urb(urb, dev->udev,
+            usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
+            buf, writesize, skel_write_bulk_callback, dev);
+    urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+    usb_anchor_urb(urb, &dev->submitted);
+
+    /* send the data out the bulk port */
+    retval = usb_submit_urb(urb, GFP_KERNEL);
+    mutex_unlock(&dev->io_mutex);
+    if (retval) {
+        err("%s - failed submitting write urb, error %d", __func__,
+                retval);
+        goto error_unanchor;
+    }
+
+    /*
+     * release our reference to this urb, the USB core will eventually free
+     * it entirely
+     */
+    usb_free_urb(urb);
+
+
+    return writesize;
+
+error_unanchor:
+    usb_unanchor_urb(urb);
+error:
+    if (urb) {
+        usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma);
+        usb_free_urb(urb);
+    }
+    up(&dev->limit_sem);
+
+exit:
+    return retval;
+}
+
+static const struct file_operations skel_fops = {
+    .owner =        THIS_MODULE,
+    .read =         skel_read,
+    .write =        skel_write,
+    .open =         skel_open,
+    .release =      skel_release,
+    .flush =        skel_flush,
+    .llseek =       noop_llseek,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+static struct usb_class_driver skel_class = {
+    .name =         "skel%d",
+    .fops =         &skel_fops,
+    .minor_base =   USB_SKEL_MINOR_BASE,
+};
+
+static int skel_probe(struct usb_interface *interface,
+        const struct usb_device_id *id)
+{
+    struct usb_skel *dev;
+    struct usb_host_interface *iface_desc;
+    struct usb_endpoint_descriptor *endpoint;
+    size_t buffer_size;
+    int i;
+    int retval = -ENOMEM;
+
+    /* allocate memory for our device state and initialize it */
+    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+    if (!dev) {
+        err("Out of memory");
+        goto error;
+    }
+    kref_init(&dev->kref);
+    sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+    mutex_init(&dev->io_mutex);
+    spin_lock_init(&dev->err_lock);
+    init_usb_anchor(&dev->submitted);
+    init_completion(&dev->bulk_in_completion);
+
+    dev->udev = usb_get_dev(interface_to_usbdev(interface));
+    dev->interface = interface;
+
+    /* set up the endpoint information */
+    /* use only the first bulk-in and bulk-out endpoints */
+    iface_desc = interface->cur_altsetting;
+    for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+        endpoint = &iface_desc->endpoint[i].desc;
+
+        if (!dev->bulk_in_endpointAddr &&
+                usb_endpoint_is_bulk_in(endpoint)) {
+            /* we found a bulk in endpoint */
+            buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+            dev->bulk_in_size = buffer_size;
+            dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+            dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+            if (!dev->bulk_in_buffer) {
+                err("Could not allocate bulk_in_buffer");
+                goto error;
+            }
+            dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+            if (!dev->bulk_in_urb) {
+                err("Could not allocate bulk_in_urb");
+                goto error;
+            }
+        }
+
+        if (!dev->bulk_out_endpointAddr &&
+                usb_endpoint_is_bulk_out(endpoint)) {
+            /* we found a bulk out endpoint */
+            dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
+        }
+    }
+    if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
+        err("Could not find both bulk-in and bulk-out endpoints");
+        goto error;
+    }
+
+    /* save our data pointer in this interface device */
+    usb_set_intfdata(interface, dev);
+
+    /* we can register the device now, as it is ready */
+    retval = usb_register_dev(interface, &skel_class);
+    if (retval) {
+        /* something prevented us from registering this driver */
+        err("Not able to get a minor for this device.");
+        usb_set_intfdata(interface, NULL);
+        goto error;
+    }
+
+    /* let the user know what node this device is now attached to */
+    dev_info(&interface->dev,
+            "USB Skeleton device now attached to USBSkel-%d",
+            interface->minor);
+    return 0;
+
+error:
+    if (dev)
+        /* this frees allocated memory */
+        kref_put(&dev->kref, skel_delete);
+    return retval;
+}
+
+static void skel_disconnect(struct usb_interface *interface)
+{
+    struct usb_skel *dev;
+    int minor = interface->minor;
+
+    dev = usb_get_intfdata(interface);
+    usb_set_intfdata(interface, NULL);
+
+    /* give back our minor */
+    usb_deregister_dev(interface, &skel_class);
+
+    /* prevent more I/O from starting */
+    mutex_lock(&dev->io_mutex);
+    dev->interface = NULL;
+    mutex_unlock(&dev->io_mutex);
+
+    usb_kill_anchored_urbs(&dev->submitted);
+
+    /* decrement our usage count */
+    kref_put(&dev->kref, skel_delete);
+
+    dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor);
+}
+
+static void skel_draw_down(struct usb_skel *dev)
+{
+    int time;
+
+    time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+    if (!time)
+        usb_kill_anchored_urbs(&dev->submitted);
+    usb_kill_urb(dev->bulk_in_urb);
+}
+
+static int skel_suspend(struct usb_interface *intf, pm_message_t message)
+{
+    struct usb_skel *dev = usb_get_intfdata(intf);
+
+    if (!dev)
+        return 0;
+    skel_draw_down(dev);
+    return 0;
+}
+
+static int skel_resume(struct usb_interface *intf)
+{
+    return 0;
+}
+
+static int skel_pre_reset(struct usb_interface *intf)
+{
+    struct usb_skel *dev = usb_get_intfdata(intf);
+
+    mutex_lock(&dev->io_mutex);
+    skel_draw_down(dev);
+
+    return 0;
+}
+
+static int skel_post_reset(struct usb_interface *intf)
+{
+    struct usb_skel *dev = usb_get_intfdata(intf);
+
+    /* we are sure no URBs are active - no locking needed */
+    dev->errors = -EPIPE;
+    mutex_unlock(&dev->io_mutex);
+
+    return 0;
+}
+
+static struct usb_driver skel_driver = {
+    .name =         "skeleton",
+    .probe =        skel_probe,
+    .disconnect =   skel_disconnect,
+    .suspend =      skel_suspend,
+    .resume =       skel_resume,
+    .pre_reset =    skel_pre_reset,
+    .post_reset =   skel_post_reset,
+    .id_table =     skel_table,
+    .supports_autosuspend = 1,
+};
+
+static int __init usb_skel_init(void)
+{
+    int result;
+
+    /* register this driver with the USB subsystem */
+    result = usb_register(&skel_driver);
+    if (result)
+        err("usb_register failed. Error number %d", result);
+
+    return result;
+}
+
+static void __exit usb_skel_exit(void)
+{
+    /* deregister this driver with the USB subsystem */
+    usb_deregister(&skel_driver);
+}
+
+module_init(usb_skel_init);
+module_exit(usb_skel_exit);
+
+MODULE_LICENSE("GPL");
+