summaryrefslogtreecommitdiff
path: root/openpicc/os/usb/USBIsr.c
diff options
context:
space:
mode:
authorhenryk <henryk@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2007-11-06 20:26:48 +0000
committerhenryk <henryk@6dc7ffe9-61d6-0310-9af1-9938baff3ed1>2007-11-06 20:26:48 +0000
commit633c646ab36368caf6eaeedd326d9f1835196afd (patch)
treefdd0f60747745d3e528c0f5d8f8895b26fb79633 /openpicc/os/usb/USBIsr.c
parent3b41196cb6b64cf6ba8ba41d6995428f73d4764a (diff)
Initial import of FreeRTOS code for OpenPICC
git-svn-id: https://svn.openpcd.org:2342/trunk@311 6dc7ffe9-61d6-0310-9af1-9938baff3ed1
Diffstat (limited to 'openpicc/os/usb/USBIsr.c')
-rw-r--r--openpicc/os/usb/USBIsr.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/openpicc/os/usb/USBIsr.c b/openpicc/os/usb/USBIsr.c
new file mode 100644
index 0000000..cbc5f85
--- /dev/null
+++ b/openpicc/os/usb/USBIsr.c
@@ -0,0 +1,169 @@
+/*
+ FreeRTOS.org V4.2.1 - Copyright (C) 2003-2007 Richard Barry.
+
+ This file is part of the FreeRTOS.org distribution.
+
+ FreeRTOS.org 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ FreeRTOS.org 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
+ along with FreeRTOS.org; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ A special exception to the GPL can be applied should you wish to distribute
+ a combined work that includes FreeRTOS.org, without being obliged to provide
+ the source code for any proprietary components. See the licensing section
+ of http://www.FreeRTOS.org for full details of how and when the exception
+ can be applied.
+
+ ***************************************************************************
+ See http://www.FreeRTOS.org for documentation, latest information, license
+ and contact details. Please ensure to read the configuration and relevant
+ port sections of the online documentation.
+ ***************************************************************************
+*/
+
+
+/*
+ BASIC INTERRUPT DRIVEN DRIVER FOR USB.
+
+ This file contains all the usb components that must be compiled
+ to ARM mode. The components that can be compiled to either ARM or THUMB
+ mode are contained in USB-CDC.c.
+
+*/
+
+/* Scheduler includes. */
+#include <FreeRTOS.h>
+#include <task.h>
+#include <queue.h>
+
+/* Demo application includes. */
+#include <board.h>
+#include <usb.h>
+#include <USB-CDC.h>
+
+#define usbINT_CLEAR_MASK (AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 )
+/*-----------------------------------------------------------*/
+
+/* Messages and queue used to communicate between the ISR and the USB task. */
+static xISRStatus xISRMessages[usbQUEUE_LENGTH + 1];
+extern xQueueHandle xUSBInterruptQueue;
+/*-----------------------------------------------------------*/
+
+/* The ISR can cause a context switch so is declared naked. */
+void vUSB_ISR (void) __attribute__ ((naked));
+
+/*-----------------------------------------------------------*/
+
+
+void
+vUSB_ISR (void)
+{
+ /* This ISR can cause a context switch. Therefore a call to the
+ portENTER_SWITCHING_ISR() macro is made. This must come BEFORE any
+ stack variable declarations. */
+ portENTER_SWITCHING_ISR ();
+
+ /* Now variables can be declared. */
+ portCHAR cTaskWokenByPost = pdFALSE;
+ static volatile unsigned portLONG ulNextMessage = 0;
+ xISRStatus *pxMessage;
+ unsigned portLONG ulRxBytes;
+ unsigned portCHAR ucFifoIndex;
+
+ /* Use the next message from the array. */
+ pxMessage = &(xISRMessages[(ulNextMessage & usbQUEUE_LENGTH)]);
+ ulNextMessage++;
+
+ /* Save UDP ISR state for task-level processing. */
+ pxMessage->ulISR = AT91C_BASE_UDP->UDP_ISR;
+ pxMessage->ulCSR0 = AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0];
+
+ /* Clear interrupts from ICR. */
+ AT91C_BASE_UDP->UDP_ICR = AT91C_BASE_UDP->UDP_IMR | AT91C_UDP_ENDBUSRES;
+
+
+ /* Process incoming FIFO data. Must set DIR (if needed) and clear RXSETUP
+ before exit. */
+
+ /* Read CSR and get incoming byte count. */
+ ulRxBytes = (pxMessage->ulCSR0 >> 16) & usbRX_COUNT_MASK;
+
+ /* Receive control transfers on endpoint 0. */
+ if (pxMessage->ulCSR0 & (AT91C_UDP_RXSETUP | AT91C_UDP_RX_DATA_BK0))
+ {
+ /* Save FIFO data buffer for either a SETUP or DATA stage */
+ for (ucFifoIndex = 0; ucFifoIndex < ulRxBytes; ucFifoIndex++)
+ {
+ pxMessage->ucFifoData[ucFifoIndex] =
+ AT91C_BASE_UDP->UDP_FDR[usbEND_POINT_0];
+ }
+
+ /* Set direction for data stage. Must be done before RXSETUP is
+ cleared. */
+ if ((AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] & AT91C_UDP_RXSETUP))
+ {
+ if (ulRxBytes
+ && (pxMessage->ucFifoData[usbREQUEST_TYPE_INDEX] & 0x80))
+ {
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] |= AT91C_UDP_DIR;
+
+ /* Might not be wise in an ISR! */
+ while (!
+ (AT91C_BASE_UDP->
+ UDP_CSR[usbEND_POINT_0] & AT91C_UDP_DIR));
+ }
+
+ /* Clear RXSETUP */
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] &= ~AT91C_UDP_RXSETUP;
+
+ /* Might not be wise in an ISR! */
+ while (AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] & AT91C_UDP_RXSETUP);
+ }
+ else
+ {
+ /* Clear RX_DATA_BK0 */
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] &= ~AT91C_UDP_RX_DATA_BK0;
+
+ /* Might not be wise in an ISR! */
+ while (AT91C_BASE_UDP->
+ UDP_CSR[usbEND_POINT_0] & AT91C_UDP_RX_DATA_BK0);
+ }
+ }
+
+ /* If we received data on endpoint 1, disable its interrupts until it is
+ processed in the main loop */
+ if (AT91C_BASE_UDP->
+ UDP_CSR[usbEND_POINT_1] & (AT91C_UDP_RX_DATA_BK0 |
+ AT91C_UDP_RX_DATA_BK1))
+ {
+ AT91C_BASE_UDP->UDP_IDR = AT91C_UDP_EPINT1;
+ }
+
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_0] &=
+ ~(AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT);
+
+ /* Clear interrupts for the other endpoints, retain data flags for endpoint
+ 1. */
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_1] &=
+ ~(AT91C_UDP_TXCOMP | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP);
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_2] &= ~usbINT_CLEAR_MASK;
+ AT91C_BASE_UDP->UDP_CSR[usbEND_POINT_3] &= ~usbINT_CLEAR_MASK;
+
+ /* Post ISR data to queue for task-level processing */
+ cTaskWokenByPost =
+ xQueueSendFromISR (xUSBInterruptQueue, &pxMessage, cTaskWokenByPost);
+
+ /* Clear AIC to complete ISR processing */
+ AT91C_BASE_AIC->AIC_EOICR = 0;
+
+ /* Do a task switch if needed */
+portEXIT_SWITCHING_ISR (cTaskWokenByPost)}
personal git repositories of Harald Welte. Your mileage may vary